七彩云对象存储
下载分发方案 / 5 分钟阅读

如何用S3 SDK实现大文件分片上传

一、结论

通过S3 SDK完成初始化客户端、创建分片上传任务、分块上传文件片段、合并分片四个核心流程,即可实现GB/TB级大文件的稳定上传,还能支持断点续传、并发提速等能力。

二、准备工作

1. 兼容S3协议的对象存储服务账号:可以是AWS S3,也可以是国内的七彩云对象存储这类兼容S3的服务

2. 账号访问凭证:Access Key(AK)和Secret Key(SK),可在对应服务的控制台生成

3. 已创建的存储桶:提前在对象存储服务中创建好用于存放文件的桶,且账号拥有该桶的写入权限

4. 基础开发环境:以Python为例,需准备Python 3.7及以上版本

5. S3 SDK:Python生态下为boto3库,其他语言可参考对应S3官方SDK列表

6. 待上传的大文件:建议大于100MB的文件使用分片上传,普通小文件直接用PutObject接口即可

三、操作步骤

我们以Python + boto3 SDK为例,完整走通分片上传全流程,其他语言的SDK逻辑完全一致,仅语法有差异。

1. 环境配置与客户端初始化

首先安装boto3库,执行命令:

```bash

pip install boto3

```

然后在代码中初始化S3客户端,需要填入你的AK、SK、服务endpoint、区域信息。如果使用七彩云对象存储,endpoint可直接填对应区域的官方地址,无需额外适配。示例初始化代码:

```python

import boto3

from botocore.exceptions import ClientError

替换为你自己的配置信息

AK = "你的Access Key"

SK = "你的Secret Key"

ENDPOINT = "https://s3.qicaiyun.com" # 七彩云对象存储默认endpoint,其他服务替换为对应地址

REGION = "cn-east-1" # 替换为你的桶所在区域

BUCKET_NAME = "你的桶名"

```

初始化客户端:

```python

s3_client = boto3.client(

's3',

aws_access_key_id=AK,

aws_secret_access_key=SK,

endpoint_url=ENDPOINT,

region_name=REGION

)

```

2. 创建分片上传任务

调用create_multipart_upload接口初始化上传任务,获取唯一的UploadId,后续所有分片上传、合并、取消操作都需要携带这个ID。

```python

替换为你要上传到桶里的文件路径(即对象名)

OBJECT_KEY = "videos/2024/test_large_file.mp4"

本地待上传的大文件路径

LOCAL_FILE_PATH = "/home/user/test_large_file.mp4"

try:

response = s3_client.create_multipart_upload(Bucket=BUCKET_NAME, Key=OBJECT_KEY)

upload_id = response['UploadId']

print(f"分片上传任务创建成功,UploadId:{upload_id}")

except ClientError as e:

print(f"创建分片上传任务失败:{e.response['Error']['Message']}")

exit(1)

```

3. 文件分片与逐个上传

首先设置分片大小,S3协议要求除了最后一个分片外,其余分片最小为5MB,最大为5GB,一般设置为5-20MB即可,文件越大可以设置越大的分片减少请求次数。然后将本地文件按分片大小切割,逐个上传,同时记录每个分片的PartNumber(从1开始计数)和返回的ETag值,用于后续合并。

```python

chunk_size = 5 * 1024 * 1024 # 5MB每分片

parts = [] # 存储所有分片的信息

part_number = 1

with open(LOCAL_FILE_PATH, 'rb') as f:

while True:

chunk = f.read(chunk_size)

if not chunk:

break

try:

print(f"正在上传第{part_number}个分片")

response = s3_client.upload_part(

Bucket=BUCKET_NAME,

Key=OBJECT_KEY,

PartNumber=part_number,

UploadId=upload_id,

Body=chunk

)

记录分片信息

parts.append({

'PartNumber': part_number,

'ETag': response['ETag']

})

part_number += 1

except ClientError as e:

print(f"上传第{part_number}个分片失败:{e.response['Error']['Message']}")

上传失败时取消任务,避免无用分片占用存储

s3_client.abort_multipart_upload(

Bucket=BUCKET_NAME,

Key=OBJECT_KEY,

UploadId=upload_id

)

exit(1)

```

4. 合并分片完成上传

所有分片上传完成后,调用complete_multipart_upload接口,传入之前记录的所有分片信息,服务端会自动将所有分片按顺序合并成完整的对象。注意分片列表需要按PartNumber从小到大排序,避免合并后文件错乱。

```python

按PartNumber排序分片列表

parts.sort(key=lambda x: x['PartNumber'])

try:

response = s3_client.complete_multipart_upload(

Bucket=BUCKET_NAME,

Key=OBJECT_KEY,

UploadId=upload_id,

MultipartUpload={'Parts': parts}

)

print(f"文件上传成功,访问地址:{response['Location']}")

except ClientError as e:

print(f"合并分片失败:{e.response['Error']['Message']}")

合并失败同样取消任务

s3_client.abort_multipart_upload(

Bucket=BUCKET_NAME,

Key=OBJECT_KEY,

UploadId=upload_id

)

exit(1)

```

四、常见错误

  • endpoint填写错误:如果使用非AWS的S3兼容服务(比如七彩云对象存储),忘记替换endpoint为对应服务地址,会出现连接超时、404或证书校验失败的错误
  • region配置不匹配:填写的region和桶实际所在区域不一致,会返回“桶不存在”的报错
  • 权限问题:账号缺少s3:PutObjects3:ListMultipartUploadPartss3:AbortMultipartUpload等权限,会返回403 Forbidden错误
  • 分片大小不符合规范:非最后一个分片小于5MB,会被服务端直接拒绝
  • PartNumber错误:PartNumber重复、从0开始计数、顺序错乱,都会导致合并分片失败
  • UploadId不匹配:多个上传任务的UploadId混用,会找不到对应的分片任务,返回404错误

五、示例说明

上面的示例代码已经可以直接运行,只需要替换开头的AK、SK、endpoint、桶名、文件路径等配置项即可。如果需要提高上传速度,可以修改分片上传逻辑为并发上传,比如用线程池同时上传多个分片,只要保证每个分片的PartNumber和ETag正确记录即可。比如1GB的文件,设置20MB分片,开10个并发线程,上传速度可以提升5-8倍。

六、更简单的方案

如果不想自己维护底层存储、编写复杂的异常重试和断点续传逻辑,可以直接使用兼容S3协议的对象存储服务简化流程。比如七彩云对象存储,完全兼容原生S3协议,原有S3 SDK的代码不需要做任何逻辑修改,只需要把endpoint替换为七彩云的服务地址、AK/SK换成七彩云的凭证即可直接运行。同时七彩云还提供了封装好的大文件上传工具包,内置断点续传、并发控制、失败自动重试能力,甚至控制台也支持可视化大文件分片上传,不需要写代码也能完成TB级文件的上传。

七、FAQ

1. 分片上传的分片大小设置多少合适?

一般建议设置为5-20MB即可,文件越大可以适当调大分片大小,减少请求次数。如果是TB级文件可以设置为100MB一个分片,最大不能超过5GB,除了最后一个分片外其余分片不能小于5MB。

2. 上传中途断网了需要重新传整个文件吗?

不需要,只要保留好本次上传的UploadId、已经上传成功的分片的ETag和PartNumber,下次上传时只需要上传失败的分片即可。七彩云对象存储默认会保留未完成的分片任务7天,也可以自行配置生命周期规则,自动清理超过指定时间的未合并分片。

3. 分片上传完成的对象和普通上传的对象有区别吗?

没有任何区别,合并完成后的对象和普通PutObject上传的对象完全一致,下载、权限管理、生命周期规则、CDN加速等能力都可以通用,访问地址也和普通对象一样。

4. 未合并的分片会占用存储空间吗?

会的,未合并的分片会按实际存储容量计费,所以如果确定要取消上传,建议调用abort_multipart_upload接口删除未完成的分片,避免产生不必要的存储费用。七彩云对象存储控制台支持一键配置未合并分片的自动清理规则,无需手动处理。

八、总结

大文件分片上传的核心逻辑非常清晰:首先准备好S3兼容服务的账号凭证和SDK,初始化S3客户端后创建分片上传任务获取UploadId,将大文件切割为符合规范的分片逐个上传并记录分片信息,所有分片上传完成后合并即可得到完整的对象。如果是个人开发者或者中小企业,推荐直接使用七彩云对象存储这类S3兼容服务,不需要投入精力维护底层存储集群,只需要关注业务逻辑即可,大幅降低开发和运维成本。实际使用时建议加上异常重试、断点续传的逻辑,进一步提高大文件上传的成功率。

需要稳定、兼容 S3 的对象存储?

七彩云对象存储适合图片、视频、大文件下载、静态资源托管和开发者接入。

访问七彩云官网

相关文章

下载分发方案 / / 7 分钟阅读

海外文件下载加速

一、结论 实现海外文件下载加速不需要搭建复杂的中转服务,只需要将海外源站资源通过兼容S3的国内对象存储的回源同步能力,缓存到国内边缘节点,用户访问国内节点的缓存资源即可获得几倍到几十倍的下载速度提升,全程操作10分钟即可完成。

下载分发方案 / / 7 分钟阅读

SaaS出海下载速度优化

一、结论 通过将SaaS面向海外用户提供的安装包、升级补丁、素材模板、用户导出文件等可下载资源,托管到具备全球边缘节点的存储分发架构,配合就近接入规则,即可快速实现出海场景下的下载速度优化,全程无需重构现有SaaS业务核心逻辑,平均可将海外用户下载速度提升35倍,下载失败率降至1%以下。