一、结论
通过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:PutObject、s3:ListMultipartUploadParts、s3: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 的对象存储?
七彩云对象存储适合图片、视频、大文件下载、静态资源托管和开发者接入。
访问七彩云官网