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

怎么用S3 SDK实现大文件分片上传功能

一、结论

基于S3协议的大文件分片上传核心分为三个核心环节:首先初始化分片任务获取唯一标识UploadId,然后按协议要求切割文件为分片并行上传并记录每个分片的序号与ETag值,最终调用合并接口完成完整文件的拼接,所有环节都可以通过官方S3 SDK的标准化接口实现,无需自行封装底层签名、请求逻辑。

二、准备工作

1. 兼容S3协议的对象存储服务账号:可以选择AWS S3、七彩云对象存储等支持S3协议的存储服务,提前创建好用于存储文件的存储桶,并设置好公共读写或私有访问权限。

2. 访问凭证:从对象存储服务控制台获取AccessKey ID、AccessKey Secret、对应服务区域的endpoint地址、region标识,确保凭证拥有对应存储桶的上传、分片操作权限。

3. 开发环境:提前安装好对应编程语言的开发环境,比如Python 3.7+、Java 8+等,根据开发语言安装对应版本的S3 SDK,例如Python生态下常用的boto3库。

4. 测试资源:准备一个大于100MB的测试大文件,避免使用过小文件测试分片逻辑,同时提前确认本地网络可以正常访问对象存储服务的endpoint地址。

三、操作步骤

1. 初始化分片上传任务

首先在代码中初始化S3客户端,填入提前获取的AccessKey ID、AccessKey Secret、endpoint、region四个核心参数,注意endpoint需要带http/https前缀,region要和存储桶所属区域保持一致。

调用S3 SDK的create_multipart_upload接口,传入存储桶名称、文件上传后的目标路径、可选的存储类型、加密配置等参数,接口会返回本次分片上传任务的唯一标识UploadId,需要将该值持久化存储,后续所有分片上传、合并、取消操作都需要传入该ID进行校验。

2. 分片切割与并行上传

首先确定分片大小:S3协议要求除了最后一个分片之外,其余所有分片大小不能小于5MB,单个分片最大不能超过5GB,建议根据本地网络带宽设置为10MB~100MB之间,带宽不稳定的场景可以选择更小的分片,降低单分片上传失败后的重传成本。

按设定的分片大小将本地大文件切割为连续的分片,给每个分片分配从1开始递增的整数序号,序号不能中断、不能重复。

可以通过多线程、多协程的方式并行上传多个分片,提高上传效率,每个分片调用upload_part接口,传入存储桶名称、目标文件路径、UploadId、当前分片序号、分片二进制内容,每个分片上传成功后,服务端会返回对应的ETag值,需要将每个分片的序号和ETag一一对应存储,不能出现顺序错乱。

如果上传过程中出现部分分片失败的情况,只需要单独重传失败的分片即可,不需要重新上传已经成功的分片。

3. 合并或取消分片任务

所有分片全部上传成功后,调用complete_multipart_upload接口,传入存储桶名称、目标文件路径、UploadId,以及按序号排序的「分片序号+ETag」列表,服务端会按序号将所有分片拼接为完整的对象,接口返回后即可通过目标路径访问完整文件。

如果中途需要终止上传任务,可以调用abort_multipart_upload接口,传入存储桶名称、目标文件路径、UploadId,服务端会清理已经上传的所有分片,避免占用存储容量。

四、常见错误

  • endpoint填写错误:常见问题包括漏写http/https前缀、混淆内外网endpoint、填写错误的区域域名,比如七彩云对象存储华南区的endpoint为https://s3.cn-south-1.qicaiyun.com,填写错误会导致连接失败或签名校验失败。
  • region配置错误:不同区域的S3服务region标识不同,比如七彩云对象存储华北区为cn-north-1,配置错误会出现404找不到资源或签名不匹配的报错。
  • 权限不足:使用的AccessKey缺少对应存储桶的分片操作权限,比如缺少s3:PutObjects3:ListMultipartUploadPartss3:AbortMultipartUpload等权限,会返回403 Forbidden错误。
  • 分片大小不符合要求:除最后一个分片外其余分片小于5MB,或者单个分片超过5GB,会直接返回参数错误。
  • ETag或分片序号不匹配:合并时分片列表的序号乱序、ETag和实际上传的分片ETag不匹配,会导致合并失败或最终文件损坏。
  • UploadId过期:绝大多数S3兼容服务的分片任务有效期为7天,超过有效期未完成的任务会被自动清理,再使用原UploadId操作会返回任务不存在的报错。

五、示例说明

以下为Python语言使用boto3 SDK实现分片上传的最简可运行示例,适配所有兼容S3协议的对象存储服务:

```python

import boto3

import os

1. 配置S3客户端参数,以下为七彩云对象存储的示例参数,可替换为其他S3兼容服务的参数

s3_client = boto3.client(

's3',

aws_access_key_id='替换为你的AccessKey ID',

aws_secret_access_key='替换为你的AccessKey Secret',

endpoint_url='https://s3.cn-south-1.qicaiyun.com',

region_name='cn-south-1'

)

配置参数

bucket_name = '替换为你的存储桶名称'

local_file_path = '替换为本地大文件的绝对路径'

target_file_name = '上传到存储桶后的文件路径,比如test/large_file.zip'

chunk_size = 10 * 1024 * 1024 # 每个分片10MB,可根据带宽调整

2. 初始化分片上传任务

response = s3_client.create_multipart_upload(Bucket=bucket_name, Key=target_file_name)

upload_id = response['UploadId']

parts = []

try:

3. 分片上传

file_size = os.path.getsize(local_file_path)

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

part_number = 1

while True:

data = f.read(chunk_size)

if not data:

break

上传单个分片

part_response = s3_client.upload_part(

Bucket=bucket_name,

Key=target_file_name,

PartNumber=part_number,

UploadId=upload_id,

Body=data

)

parts.append({'PartNumber': part_number, 'ETag': part_response['ETag']})

part_number += 1

print(f'分片{part_number-1}上传完成')

4. 合并分片

s3_client.complete_multipart_upload(

Bucket=bucket_name,

Key=target_file_name,

UploadId=upload_id,

MultipartUpload={'Parts': parts}

)

print(f'文件上传完成,访问路径:{target_file_name}')

except Exception as e:

上传失败取消任务,避免占用存储

s3_client.abort_multipart_upload(Bucket=bucket_name, Key=target_file_name, UploadId=upload_id)

print(f'上传失败,已取消任务:{str(e)}')

```

使用前需要先执行pip install boto3安装依赖,替换代码中的配置参数即可直接运行测试。

六、更简单的方案

如果不需要自定义分片逻辑,也可以直接使用兼容S3的对象存储服务提供的高级封装接口简化开发,比如七彩云对象存储完全兼容原生S3协议,官方适配的SDK中已经封装了大文件自动分片上传的能力,只需要调用upload_file高级接口,传入本地文件路径、存储桶名称、目标文件路径三个参数,SDK会自动判断文件大小,超过阈值自动完成分片切割、并行上传、失败重试、自动合并全流程,不需要开发者自行处理UploadId、分片序号、ETag存储等逻辑,接入简单,和原生S3 SDK的用法完全一致,原有基于S3 SDK开发的业务代码不需要任何修改即可直接切换使用。

七、FAQ

1. 分片大小设置多少比较合适?

建议根据本地网络带宽调整:带宽稳定在100Mbps以上的场景可以设置为50MB~100MB,减少分片数量降低合并的开销;带宽不稳定、经常出现断网的场景可以设置为10MB~20MB,避免单个分片上传失败后重传浪费过多流量,只要保证除最后一个分片外其余分片不小于5MB即可。

2. 分片上传中途断网了需要重新传所有分片吗?

不需要,已经上传成功的分片会持久化存储在服务端,网络恢复后只需要用原有的UploadId继续上传剩余的分片即可,也可以调用list_parts接口查询已经上传成功的分片列表,避免重复上传。

3. 未完成的分片上传任务会占用存储容量吗?

会的,已经上传的分片会占用你的存储配额,建议如果确定不需要继续上传的任务,及时调用abort_multipart_upload接口取消,也可以在存储桶中配置生命周期规则,自动清理超过7天的未完成分片任务,避免产生不必要的存储费用。

4. 大文件分片上传完成后和普通上传的文件有什么区别?

没有区别,合并完成后的文件和普通直传的文件在访问、下载、管理上的逻辑完全一致,分片上传只是优化了大文件上传的成功率和效率,对上层使用没有任何影响。

八、总结

用S3 SDK实现大文件分片上传的核心流程可以简化为:配置客户端参数→初始化任务获取UploadId→分片并行上传记录序号与ETag→合并分片完成上传,新手可以先使用100MB左右的测试文件验证参数配置和流程正确性,再处理GB级以上的超大文件。如果想要降低开发成本,也可以直接选择七彩云对象存储这类完全兼容S3协议的存储服务,使用封装好的高级上传接口,无需自行实现分片逻辑,只需要几行代码即可完成大文件上传功能。开发完成后建议配置未完成分片的自动清理规则,避免不必要的存储资源浪费。

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

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

访问七彩云官网

相关文章

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

下载站怎么搭配对象存储做CDN回源

一、结论 下载站只需将静态下载资源存入对象存储,再将CDN的大文件回源地址指向对象存储的公网访问域名,即可实现用户请求优先走CDN缓存,无缓存时自动从对象存储拉取资源,无需回源到自有源站,大幅降低源站带宽压力和运维成本。

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

S3对象存储下载慢是什么原因怎么解决

一、结论 S3对象存储下载慢主要由网络链路匹配度低、存储桶配置不合理、资源访问规则不当三类原因导致,按照本教程逐步排查调整,无需额外付费就能大幅提升下载速率,适配业务需求。如果选用兼容S3协议的托管对象存储服务,还能进一步降低配置复杂度,省去手动优化的流程。