You need to enable JavaScript to run this app.
最新活动
大模型
产品
解决方案
定价
生态与合作
支持与服务
开发者
了解我们

使用boto3进行Multipart upload遇阻,求概念与语法详解

S3 Multipart Upload 概念详解与Boto3实现细节

嘿,我来帮你把S3分片上传的事儿掰扯清楚——这玩意儿初上手确实容易踩坑,咱们从概念到Boto3的具体实现一步步来。

什么是Multipart Upload?

简单来说,这是AWS S3针对大文件(或者不稳定网络环境)设计的上传机制:把一个大文件拆成多个**小分片(Part)**分别上传,等所有分片都传完后,再让S3把这些分片合并成一个完整的文件。

它的核心优势:

  • 某个分片传失败了?不用重新传整个文件,只重传那个出错的分片就行
  • 可以并行上传多个分片,大幅提升上传速度
  • 天然支持断点续传,中途断网了下次接着传就行

AWS官方建议:当文件大小超过100MB时,优先使用分片上传;如果文件超过5GB,那必须用分片上传(普通上传不支持这么大的文件)。

Boto3实现Multipart Upload的完整流程

Boto3的S3客户端提供了三个核心方法来完成整个流程,咱们逐个拆解:

1. 初始化分片上传(create_multipart_upload

这一步相当于给S3打个招呼:“我要开始传一个大文件啦,给我个专属ID呗”。S3会返回一个唯一的UploadId,后续所有分片上传、合并操作都得带着这个ID。

代码示例

import boto3

# 初始化S3客户端
s3_client = boto3.client('s3')

# 发起分片上传请求
response = s3_client.create_multipart_upload(
    Bucket='your-bucket-name',  # 你的S3桶名
    Key='documents/large-report.pdf'  # 文件在桶里的路径/文件名
)

# 保存关键的UploadId
upload_id = response['UploadId']

语法细节

  • BucketKey是必填参数,Key就是文件最终在S3中的存储路径
  • 你还可以加额外参数,比如ContentType='application/pdf'指定文件类型,ACL='private'设置文件权限,这些和普通S3上传的参数逻辑一致
  • 如果请求成功,响应里的UploadId是后续操作的核心凭证,一定要保存好

2. 上传分片(upload_part

这一步是把文件拆成多个分片,逐个(或者并行)上传到S3。每个分片需要指定唯一的PartNumber(从1开始的整数),上传完成后S3会返回一个ETag——这个是后续合并分片的关键标识。

代码示例

# 定义分片大小:这里设为10MB(AWS建议最小5MB,最大5GB)
part_size = 10 * 1024 * 1024  # 10MB
uploaded_parts = []

# 读取本地大文件并分片上传
with open('local-large-report.pdf', 'rb') as file:
    part_number = 1
    while True:
        # 读取当前分片的内容
        chunk_data = file.read(part_size)
        # 如果没有数据了,说明已经到文件末尾
        if not chunk_data:
            break
        
        # 上传当前分片
        part_response = s3_client.upload_part(
            Bucket='your-bucket-name',
            Key='documents/large-report.pdf',
            PartNumber=part_number,
            UploadId=upload_id,
            Body=chunk_data
        )
        
        # 保存分片的序号和ETag,后续合并要用
        uploaded_parts.append({
            'PartNumber': part_number,
            'ETag': part_response['ETag']
        })
        
        part_number += 1

语法细节

  • PartNumber必须是1到10000之间的整数,每个分片的序号不能重复
  • 分片大小要求:除了最后一个分片,其他分片的大小必须≥5MB;最后一个分片可以任意大小(哪怕小于5MB)
  • 你可以并行上传分片(比如用多线程/多进程),不用按顺序传,但一定要记录好每个分片的PartNumberETag
  • 如果某个分片上传失败,直接重新上传这个分片就行,不用管其他已经传好的

3. 完成分片上传(complete_multipart_upload

当所有分片都上传成功后,把收集到的分片信息(PartNumberETag)提交给S3,S3会自动把这些分片合并成一个完整的文件,正式完成上传任务。

代码示例

# 提交合并请求前,一定要把分片按PartNumber升序排序
sorted_parts = sorted(uploaded_parts, key=lambda x: x['PartNumber'])

# 完成分片上传
complete_response = s3_client.complete_multipart_upload(
    Bucket='your-bucket-name',
    Key='documents/large-report.pdf',
    UploadId=upload_id,
    MultipartUpload={
        'Parts': sorted_parts
    }
)

# 合并成功后,会返回文件的S3地址
print(f"文件上传完成,地址:{complete_response['Location']}")

语法细节

  • MultipartUpload['Parts']必须是按PartNumber升序排列的列表,哪怕你是乱序上传的分片,这里也必须排序
  • 如果合并成功,S3会删除所有临时存储的分片,只保留合并后的完整文件
  • 如果有分片上传失败,你可以选择放弃整个任务(看下面的中止方法),避免S3保留无用的分片占用存储空间

额外:中止分片上传(abort_multipart_upload

如果中途不想继续上传了,或者出现无法修复的错误,一定要调用这个方法来中止任务,不然S3会在7天后自动清理这些临时分片,但主动调用更稳妥,能及时释放存储空间。

代码示例

s3_client.abort_multipart_upload(
    Bucket='your-bucket-name',
    Key='documents/large-report.pdf',
    UploadId=upload_id
)

常见坑点提醒

  • 分片大小别搞错:除了最后一个分片,其他必须≥5MB,不然会直接报错
  • ETag一定要保存正确:每个分片的ETag是S3返回的字符串,不能自己生成,否则合并时会失败
  • PartNumber范围要注意:必须在1到10000之间,不能重复
  • 合并前一定要排序:哪怕你并行上传的分片顺序乱了,提交Parts的时候必须按PartNumber升序排列

内容的提问来源于stack exchange,提问作者Ganesh Shinde

火山引擎 最新活动