
本文详解如何绕过 S3 单次 CopyObject 5GB 限制,通过手动分段 + UploadPartCopy 实现大对象重命名,关键在于显式指定 CopySourceRange 而非依赖 ListParts。
本文详解如何绕过 s3 单次 `copyobject` 5gb 限制,通过手动分段 + `uploadpartcopy` 实现大对象重命名,关键在于显式指定 `copysourcerange` 而非依赖 `listparts`。
在 AWS S3 中,CopyObject API 仅支持最大 5 GB 的单次拷贝;超过该大小的对象重命名(即逻辑“移动”)必须使用分段上传(Multipart Upload)机制。但需注意:S3 并不提供自动分片的“分段拷贝”原生接口——ListParts 操作针对的是 已发起的 Multipart Upload 任务中的已上传分片,而源对象本身是普通对象,无预定义分片结构。因此,错误地调用 ListParts 查询源对象分片(如问题中第二段代码)必然返回空结果。
正确做法是:由客户端主动计算源对象字节范围,对每个分段显式调用 UploadPartCopy 并设置 CopySourceRange 字段。以下是完整、健壮的 Go 实现:
import (
"context"
"math"
"github.com/aws/aws-sdk-go/aws"
"github.com/aws/aws-sdk-go/aws/session"
"github.com/aws/aws-sdk-go/service/s3"
)
func copyS3ObjectWithMultipart(
svc *s3.S3,
bucket, sourceKey, targetKey string,
partSize int64, // 推荐 5MB ~ 5GB,需为 1MB 倍数(除最后一段)
) error {
// 1. 获取源对象大小(必需)
headResp, err := svc.HeadObject(&s3.HeadObjectInput{
Bucket: aws.String(bucket),
Key: aws.String(sourceKey),
})
if err != nil {
return err
}
totalSize := *headResp.ContentLength
// 2. 创建分段上传任务
createResp, err := svc.CreateMultipartUpload(&s3.CreateMultipartUploadInput{
Bucket: aws.String(bucket),
Key: aws.String(targetKey),
})
if err != nil {
return err
}
uploadID := *createResp.UploadId
// 3. 分段拷贝:计算每段起止字节并调用 UploadPartCopy
var parts []*s3.CompletedPart
for start := int64(0); start <p>✅ <strong>关键要点与注意事项</strong>:</p>
-
CopySource格式必须为bucket/key(而非s3://bucket/key或仅key),否则报错; -
CopySourceRange是必需字段,格式为"bytes=start-end"(含首尾,如"bytes=0-5242879"表示前 5MB); - 分段大小建议 ≥ 5 MB(最小允许值),且除最后一段外,所有分段应为 1 MB 的整数倍;
-
务必处理异常并调用
AbortMultipartUpload,避免产生孤儿上传(占用存储且产生费用); - 若需高可靠性,可加入重试逻辑(如
github.com/aws/aws-sdk-go/aws/request.Retryer); - 对于超大对象(TB 级),建议结合并发(控制 goroutine 数量)与进度日志。
该方案完全规避了 CopyObject 的尺寸限制,是 S3 大对象重命名/迁移的标准实践。










