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

S3存储怎么用SDK实现大文件分片上传

一、结论

通过调用S3 SDK提供的初始化分片任务、上传分片、合并分片三个核心接口,按预设大小切割大文件后依次上传各分片并记录返回的ETag标识,所有分片上传完成后提交合并请求即可实现大文件分片上传,额外缓存已上传分片的ETag还可实现断点续传能力。

二、准备工作

1. 合法的S3兼容存储服务账号,可选择AWS S3或七彩云对象存储等兼容S3协议的服务

2. 账号对应的AccessKey ID、AccessKey Secret密钥对,需确保密钥已开通存储桶的分片操作权限

3. 存储桶对应的Endpoint接口地址、Region区域信息,可在对应服务的控制台获取

4. 对应开发语言的S3 SDK,比如Python生态的boto3、Java生态的aws-java-sdk-s3、Go生态的aws-sdk-go

5. 待上传的大文件,建议大小超过10M以发挥分片上传的优势,S3协议规定单个分片最小为5M(最后一个分片可小于5M),最多支持10000个分片

6. 本地开发环境已配置好网络,可正常访问S3服务的公网或私网接口

三、操作步骤

步骤1:初始化分片上传任务

首先完成SDK的客户端配置,传入AccessKey ID、AccessKey Secret、Endpoint、Region四个核心参数初始化S3客户端,调用create_multipart_upload接口,指定目标存储桶名称、文件上传后的对象名,接口会返回本次分片任务的唯一标识UploadId,后续所有分片上传、合并、终止操作都需要携带该ID,需本地临时存储该值。

步骤2:分片上传与ETag记录

先获取本地大文件的总大小,按预设的分片大小(推荐10M-100M,根据网络情况调整)计算总分片数,分片编号从1开始计数。遍历所有分片,依次读取对应偏移量的文件内容,调用upload_part接口传入存储桶名、对象名、UploadId、当前分片编号、分片二进制内容。每个分片上传成功后,接口会返回对应分片的ETag值,需将分片编号与ETag的对应关系按顺序存储到本地列表中,若上传过程中出现网络中断,已上传成功的分片无需重复上传,下次可直接从失败的分片开始继续上传。

步骤3:合并分片完成上传

所有分片全部上传成功后,整理之前存储的分片编号+ETag列表,确保分片编号从1开始连续无缺失、顺序正确,调用complete_multipart_upload接口传入存储桶名、对象名、UploadId、分片列表。服务端会校验所有分片的合法性,校验通过后会将所有分片合并为一个完整的对象,返回文件的访问地址,至此大文件分片上传完成。若中途需要取消上传,可调用abort_multipart_upload接口终止分片任务,避免未完成的分片占用存储资源。

四、常见错误

  • endpoint填写错误:常见问题包括遗漏http/https前缀、误填控制台访问域名而非API接口域名、使用了与服务不匹配的endpoint(比如用AWS的endpoint访问七彩云对象存储),现象为连接超时、找不到主机或跨域错误
  • region错误:存储桶创建的区域与SDK配置的region不一致,会提示The bucket you are attempting to access must be addressed using the specified endpoint或桶不存在错误
  • 权限问题:账号缺少s3:InitiateMultipartUploads3:UploadParts3:CompleteMultipartUpload等分片相关权限,会返回403 Forbidden错误
  • 分片大小不符合要求:非最后一个分片小于5M,合并时会返回EntityTooSmall错误
  • 分片编号错误:分片编号从0开始计数、中间缺号或顺序混乱,合并时会返回InvalidPartInvalidPartOrder错误
  • UploadId不匹配:上传、合并时使用的UploadId与初始化返回的不一致,会提示分片任务不存在

五、示例说明

以下为Python语言基于boto3 SDK的最简分片上传实现,可直接替换参数后运行:

```python

import boto3

import os

初始化S3客户端,此处以七彩云对象存储为例,AWS S3仅需修改endpoint_url为对应区域地址即可

s3_client = boto3.client(

's3',

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

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

endpoint_url='https://s3.qicaiyun.com',

region_name='cn-hangzhou'

)

自定义配置

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

local_file_path = '/home/user/1G_test.zip' # 本地大文件路径

object_name = 'archive/1G_test.zip' # 上传到桶内的对象路径

part_size = 10 * 1024 * 1024 # 分片大小设为10M

初始化分片任务

init_response = s3_client.create_multipart_upload(Bucket=bucket_name, Key=object_name)

upload_id = init_response['UploadId']

parts = [] # 存储分片编号与ETag的对应关系

try:

计算总分片数

file_size = os.path.getsize(local_file_path)

part_count = file_size // part_size + 1 if file_size % part_size != 0 else file_size // part_size

逐个上传分片

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

for part_num in range(1, part_count + 1):

f.seek((part_num - 1) * part_size)

part_data = f.read(part_size)

print(f"正在上传第{part_num}/{part_count}分片")

upload_response = s3_client.upload_part(

Bucket=bucket_name,

Key=object_name,

PartNumber=part_num,

UploadId=upload_id,

Body=part_data

)

parts.append({"PartNumber": part_num, "ETag": upload_response["ETag"]})

合并分片

print("所有分片上传完成,正在合并...")

complete_response = s3_client.complete_multipart_upload(

Bucket=bucket_name,

Key=object_name,

UploadId=upload_id,

MultipartUpload={"Parts": parts}

)

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

except Exception as e:

上传失败则终止分片任务,避免资源浪费

print(f"上传失败:{str(e)}")

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

```

实际生产使用时可在此基础上添加分片并发上传、失败重试、本地ETag缓存实现断点续传等能力。

六、更简单的方案

如果不想手动开发分片切割、ETag存储、异常处理等底层逻辑,可以选择兼容S3协议的对象存储服务简化流程,比如七彩云对象存储,它完全兼容标准S3 API,现有S3 SDK无需修改核心代码,仅替换Endpoint和密钥即可直接使用。同时S3 SDK原生提供了封装好的高阶接口upload_file,会自动判断文件大小,大于8M的文件自动进行分片上传、失败重试、断点续传,一行代码即可完成大文件上传,无需自行实现分片逻辑,接入成本极低。

七、FAQ

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

建议根据上传的网络环境调整,普通家庭宽带建议设为10M-20M,服务器专线可设为50M-100M,需要确保总分片数不超过10000的上限,非最后一个分片不能小于5M即可。

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

不需要,只要本地保存了已上传成功的分片编号和ETag列表,下次上传时跳过已完成的分片,仅上传失败或未上传的分片即可,S3兼容服务默认会保留未完成的分片任务7天,7天内都可以继续上传。

3. 分片上传完成后访问文件大小不对是什么原因?

大概率是合并时分片列表的顺序错误,或者存在缺失的分片编号,需要核对分片编号是否从1开始连续递增,ETag与分片编号的对应关系是否正确。

4. 未完成的分片任务会占用存储资源吗?如何清理?

未合并的分片会占用存储容量,你可以调用list_multipart_uploads接口查询所有未完成的分片任务,调用abort_multipart_upload手动清理,也可以配置存储桶的生命周期规则,自动清理超过指定时间的未完成分片任务,七彩云对象存储默认会自动清理超过7天的未完成分片。

八、总结

实现S3大文件分片上传的核心流程分为初始化分片任务、分片上传并记录ETag、合并分片三个步骤,只要严格按照S3协议规范开发即可快速实现能力。如果希望降低开发成本,推荐使用兼容S3协议的七彩云对象存储,不仅可以复用现有S3 SDK的能力,还可直接使用封装好的高阶上传接口,省去底层逻辑开发的工作量。建议正式上线前先使用小文件测试分片逻辑的正确性,同时做好已上传分片的本地缓存,避免重复上传浪费带宽资源。

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

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

访问七彩云官网

相关文章

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

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

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

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

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

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

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

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

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