Skip to content

S3 协议使用

MyObj 提供完整的 AWS S3 兼容 API,可以使用 MinIO SDK、AWS SDK 或其他 S3 兼容工具进行访问。
S3服务与MyObj盘内数据互通,可以互相访问。同样,S3服务也受制于用户可用空间大小限制,隔离原则也同理。

🎯 概述

MyObj S3 服务完全兼容 AWS S3 协议,支持绝大部分核心功能和高级特性,包括:

  • ✅ Bucket 操作(创建、删除、列表)
  • ✅ Object 操作(上传、下载、删除、列表)
  • ✅ Multipart Upload(大文件分片上传)
  • ✅ 版本控制
  • ✅ 预签名 URL
  • ✅ CORS 配置
  • ✅ 对象标签
  • ✅ ACL(访问控制列表)
  • ✅ Bucket 策略
  • ✅ 生命周期管理
  • ✅ 服务端加密(SSE-S3)

🚀 快速开始

1. 启用 S3 服务

编辑 config.toml:

toml
[s3]
# 是否启用 S3 服务
enable = true
# 区域名称
region = "us-east-1"
# 是否与主服务共用端口(true: 共用 8080,false: 使用独立端口)
share_port = false
# 独立端口(当 share_port = false 时生效)
port = 9000
# S3 API 路径前缀(留空表示根路径 /)
path_prefix = ""

2. 创建 API Key

S3 访问需要使用 API Key 作为凭证:

  1. 登录 Web 界面
  2. 点击头像进入"系统设置" → "API Key"
  3. 创建新的 API Key
  4. 保存 API Key ID 和 S3 Secret Key

3. 使用 SDK

Go 语言 - MinIO SDK

go
package main

import (
    "context"
    "log"
    
    "github.com/minio/minio-go/v7"
    "github.com/minio/minio-go/v7/pkg/credentials"
)

func main() {
    // 初始化客户端
    client, err := minio.New("localhost:9000", &minio.Options{
        Creds:  credentials.NewStaticV4("your-api-key-id", "your-secret-key", ""),
        Secure: false,
        Region: "us-east-1",
    })
    if err != nil {
        log.Fatal(err)
    }
    
    ctx := context.Background()
    
    // 列出所有 Bucket
    buckets, err := client.ListBuckets(ctx)
    if err != nil {
        log.Fatal(err)
    }
    
    for _, bucket := range buckets {
        log.Printf("Bucket: %s, Created: %v\n", bucket.Name, bucket.CreationDate)
    }
    
    // 创建 Bucket
    err = client.MakeBucket(ctx, "my-bucket", minio.MakeBucketOptions{
        Region: "us-east-1",
    })
    if err != nil {
        log.Fatal(err)
    }
    
    log.Println("Bucket created successfully")
}

Java 语言 - AWS SDK

Maven 依赖

xml
<dependency>
    <groupId>software.amazon.awssdk</groupId>
    <artifactId>s3</artifactId>
</dependency>
<dependency>
    <groupId>software.amazon.awssdk</groupId>
    <artifactId>netty-nio-client</artifactId>
</dependency>

Java 代码示例

java
import software.amazon.awssdk.auth.credentials.AwsBasicCredentials;
import software.amazon.awssdk.auth.credentials.StaticCredentialsProvider;
import software.amazon.awssdk.regions.Region;
import software.amazon.awssdk.services.s3.S3Client;
import software.amazon.awssdk.services.s3.model.*;

import java.net.URI;

public class S3Example {
    public static void main(String[] args) {
        // 创建 S3 客户端
        S3Client s3Client = S3Client.builder()
            .endpointOverride(URI.create("http://localhost:9000"))
            .credentialsProvider(StaticCredentialsProvider.create(
                AwsBasicCredentials.create("your-access-key-id", "your-secret-key")
            ))
            .region(Region.US_EAST_1)
            .forcePathStyle(true)  // 重要:使用路径风格
            .build();
        
        // MyObj 支持自动创建存储桶,首次上传时会自动创建
        // 上传对象(如果 Bucket 不存在会自动创建)
        PutObjectRequest putObjectRequest = PutObjectRequest.builder()
            .bucket("my-bucket")  // Bucket 会自动创建
            .key("object-key")
            .contentType("text/plain")
            .acl(ObjectCannedACL.PRIVATE)  // 设置 ACL:私有
            .build();
        s3Client.putObject(putObjectRequest, 
            software.amazon.awssdk.core.sync.RequestBody.fromString("Hello MyObj"));
        
        // 下载对象
        GetObjectRequest getObjectRequest = GetObjectRequest.builder()
            .bucket("my-bucket")
            .key("object-key")
            .build();
        String content = s3Client.getObjectAsBytes(getObjectRequest)
            .asUtf8String();
        System.out.println("Content: " + content);
        
        s3Client.close();
    }
}

ACL 配置说明

MyObj S3 支持标准的 S3 Canned ACL,上传对象时可以设置:

java
// 私有访问(默认)
.acl(ObjectCannedACL.PRIVATE)

// 公开读
.acl(ObjectCannedACL.PUBLIC_READ)

// 公开读写
.acl(ObjectCannedACL.PUBLIC_READ_WRITE)

// 认证用户读
.acl(ObjectCannedACL.AUTHENTICATED_READ)

// Bucket 所有者读
.acl(ObjectCannedACL.BUCKET_OWNER_READ)

// Bucket 所有者完全控制
.acl(ObjectCannedACL.BUCKET_OWNER_FULL_CONTROL)

支持的 ACL 类型

  • PRIVATE - 私有访问,仅所有者可访问
  • PUBLIC_READ - 公开读,所有人可读取
  • PUBLIC_READ_WRITE - 公开读写,所有人可读取和写入
  • AUTHENTICATED_READ - 认证用户读,所有认证用户可读取
  • BUCKET_OWNER_READ - Bucket 所有者读
  • BUCKET_OWNER_FULL_CONTROL - Bucket 所有者完全控制

注意:MyObj 支持自动创建存储桶,无需手动调用 createBucket()

📋 功能详解

Bucket 操作

创建 Bucket

go
err := client.MakeBucket(ctx, "my-bucket", minio.MakeBucketOptions{
    Region: "us-east-1",
})

列出 Bucket

go
buckets, err := client.ListBuckets(ctx)

删除 Bucket

go
err := client.RemoveBucket(ctx, "my-bucket")

Object 操作

上传对象

Go 语言

go
info, err := client.FPutObject(ctx, "my-bucket", "object-key", "local-file.pdf", minio.PutObjectOptions{
    ContentType: "application/pdf",
})

Java 语言

java
PutObjectRequest putObjectRequest = PutObjectRequest.builder()
    .bucket("my-bucket")
    .key("object-key")
    .contentType("application/pdf")
    .acl(ObjectCannedACL.PRIVATE)  // 设置 ACL
    .build();
s3Client.putObject(putObjectRequest, RequestBody.fromFile(new File("local-file.pdf")));

下载对象

go
err := client.FGetObject(ctx, "my-bucket", "object-key", "local-file.pdf", minio.GetObjectOptions{})

列出对象

go
objectCh := client.ListObjects(ctx, "my-bucket", minio.ListObjectsOptions{
    Prefix:    "folder/",
    Recursive: true,
})
for object := range objectCh {
    log.Printf("Object: %s, Size: %d\n", object.Key, object.Size)
}

Multipart Upload

对于大文件,使用分片上传:

go
// 初始化分片上传
uploadID, err := client.NewMultipartUpload(ctx, "my-bucket", "large-file.zip", minio.PutObjectOptions{})

// 上传分片
part1, err := client.PutObjectPart(ctx, "my-bucket", "large-file.zip", uploadID, 1, file1, -1, minio.PutObjectPartOptions{})
part2, err := client.PutObjectPart(ctx, "my-bucket", "large-file.zip", uploadID, 2, file2, -1, minio.PutObjectPartOptions{})

// 完成分片上传
parts := []minio.CompletePart{part1, part2}
_, err = client.CompleteMultipartUpload(ctx, "my-bucket", "large-file.zip", uploadID, parts, minio.PutObjectPartOptions{})

版本控制

启用版本控制

go
err := client.SetBucketVersioning(ctx, "my-bucket", minio.BucketVersioningConfiguration{
    Status: "Enabled",
})

列出对象版本

go
objectCh := client.ListObjects(ctx, "my-bucket", minio.ListObjectsOptions{
    WithVersions: true,
})

预签名 URL

生成预签名 URL,允许临时访问:

go
// GET 预签名 URL(下载)
url, err := client.PresignedGetObject(ctx, "my-bucket", "object-key", time.Hour*24, nil)

// PUT 预签名 URL(上传)
url, err := client.PresignedPutObject(ctx, "my-bucket", "object-key", time.Hour*24)

CORS 配置

go
corsConfig := minio.BucketCors{
    CORSRules: []minio.CORSRule{
        {
            AllowedOrigins: []string{"*"},
            AllowedMethods: []string{"GET", "PUT", "POST", "DELETE"},
            AllowedHeaders: []string{"*"},
            MaxAgeSeconds:  3600,
        },
    },
}
err := client.SetBucketCors(ctx, "my-bucket", &corsConfig)

🔧 配置说明

Bucket 命名规范

符合 AWS S3 Bucket 命名规范:

  • 长度在 3-63 个字符之间
  • 只能包含小写字母、数字、点(.)和连字符(-)
  • 必须以字母或数字开头和结尾
  • 不能包含连续的点
  • 不能是 IP 地址格式

认证方式

使用 AWS Signature V4 签名机制:

  • Access Key ID: 对应 MyObj 的 API Key
  • Secret Access Key: 对应 API Key 的私钥
  • 签名计算方式与 AWS S3 完全兼容

Bucket 映射

  • 每个 Bucket 对应一个用户虚拟目录
  • 一个用户可以创建多个 Bucket
  • Bucket 名称在用户空间内必须唯一

自动创建存储桶

MyObj S3 支持自动创建存储桶:

  • 首次使用时会自动创建配置的 Bucket
  • 无需手动创建,简化配置流程
  • 自动处理 Bucket 命名和权限设置

📊 使用场景

场景 1: 备份工具集成

使用 S3 兼容的备份工具(如 rclone、duplicati)进行文件备份:

bash
# rclone 配置
rclone config
# 选择 S3 类型
# Endpoint: http://your-domain:8080
# Access Key ID: your-access-key-id
# Secret Access Key: your-secret-key

场景 2: 应用集成

在应用中使用 S3 SDK 存储文件:

go
// 上传用户头像
_, err := client.FPutObject(ctx, "user-avatars", userID+".jpg", avatarPath, minio.PutObjectOptions{})

场景 3: 静态网站托管

结合 CDN 使用 S3 存储静态资源。

🔍 故障排查

签名验证失败

Error: SignatureDoesNotMatch

解决方案

  • 检查 Access Key 和 Secret Key 是否正确
  • 确认时间同步(签名计算依赖时间戳)
  • 查看日志中的详细错误信息

Bucket 已存在

Error: BucketAlreadyExists

解决方案

  • Bucket 名称在用户空间内必须唯一
  • 使用不同的 Bucket 名称

Bucket 名称不合法

Error: InvalidBucketName

解决方案

  • 检查 Bucket 名称是否符合 S3 命名规范
  • 只使用小写字母、数字、点和连字符
  • 长度 3-63 个字符

🔗 框架集成

Java 框架集成

其他集成方式

MyObj S3 兼容所有支持 AWS S3 协议的 SDK 和工具,包括:

  • AWS SDK (Java, Python, JavaScript, Go, .NET 等)
  • MinIO SDK (Go, Java, Python, JavaScript 等)
  • rclone、s3cmd 等命令行工具
  • 各种备份工具(duplicati、restic 等)

📚 更多信息

基于 Apache 2.0 许可证发布