添加链接
link之家
链接快照平台
  • 输入网页链接,自动生成快照
  • 标签化管理网页链接

分段上传允许上传单个对象作为一组分段。每个分段都是对象数据的连续部分。您可以独立上传以及按任意顺序上传这些对象分段。如果任意分段传输失败,可以重新传输该分段且不会影响其他分段。上传完所有的数据元分段后,Amazon S3 将汇集这些分段并创建数据元。一般而言,如果您的对象大小达到了 100 MB,您应该考虑使用分段上传,而不是在单个操作中上传对象。

分段上传流程

分段上分为三个步骤:开始上传、上传对象分段,以及在上传所有分段后完成分段上传。收到完成分段上传请求后,Amazon S3 将构建来自已上传分段的数据元,然后您可以像在您的存储桶中访问任何其他对象一样访问该对象。

您可以列出所有正在执行的分段上传,或者获取为特定分段上传操作上传的分段列表。以上每个操作都在本节中进行了说明。

分段上传开始

当您发送请求以开始分段上传时,Amazon S3 将返回具有上传 ID 的响应,此 ID 是分段上传的唯一标识符。无论您何时上传分段、列出分段、完成上传或停止上传,您都必须包括此上传 ID。如果您想要提供描述已上传的对象的任何元数据,必须在请求中提供它以开始分段上传。

上传分段时,除了指定上传 ID,还必须指定分段编号。您可以选择 1 和 10000 之间的任意分段编号。分段编号在您正在上传的对象中唯一地识别分段及其位置。您选择的分段编号不必是连续序列(例如,它可以是 1、5 和 14)。如果您使用之前上传的分段的同一分段编号上传新分段,则之前上传的分段将被覆盖。

无论您何时上传分段,Amazon S3 都将在其响应中返回 ETag 标头。对于每个分段上传,您必须记录分段编号和 ETag 值。您必须在随后的请求中包括这些值以完成分段上传。

分段上传完成

完成分段上传时,Amazon S3 通过按升序的分段编号规范化分段来创建对象。如果在 开始分段上传 请求中提供了任何对象元数据,则 Amazon S3 会将该元数据与对象相关联。成功 完成 请求后,分段将不再存在。

完成分段上传 请求必须包括上传 ID 以及分段编号和相应的 ETag 值的列表。Amazon S3 响应包括可唯一地识别组合对象数据的 ETag。此 ETag 无需成为对象数据的 MD5 哈希。

您可以选择停止分段上传。停止分段上传后,无法再次使用该上传 ID 上传任何分段。然后,释放取消的分段上传的任何分段的所有存储空间。如果有任何分段上传正在进行,则即使在您停止后,它们仍然可能会成功或失败。要释放所有分段使用的所有存储,必须仅在完成所有分段的上传后才停止分段上传。

参考链接: https://docs.aws.amazon.com/zh_cn/AmazonS3/latest/userguide/mpuoverview.html

示例代码:

import os
import redis
import boto3
################################## ##################################
# 把图片数据上传到本地 redis 中
conn = redis.Redis()
def store_img2redis():
    把图片数据存入到 redis 的列表中
    with open('/Users/zxk/Desktop/1min1sec.mp4', 'rb') as f:
        while True:
            bytes_data = f.read(1024 * 1024 * 6)   # 每次读取 6 M的数据
            if not bytes_data:
                return
            conn.rpush('gopher_img', bytes_data)
################################# #################################
# 把图片数据从 redis 中迭代读取出来,并分片上传到 S3 中
def list_iter(name, count=2):
    迭代获取 redis 列表中的数据
    idx = 0
    while True:
        data = conn.lrange(name, idx, idx + count - 1)
        if not data:
            return
        idx += count
        for item in data:
            yield item
client = boto3.client(
    's3',
    aws_access_key_id=os.getenv(
        'AWS_S3_ACCESS_KEY_ID', 'xxxxxxxxxxxxxxxxxxxx'),
    aws_secret_access_key=os.getenv(
        'AWS_S3_SECRET_ACCESS_KEY', 'xxyxyxxyxyxxyxyxyxxy'),
    region_name=os.getenv('AWS_S3_REGION_NAME', 'cn-northwest-1')
part_info = {
    'Parts': []
def create_multipart_upld():
    分片上传功能的函数
    response = client.create_multipart_upload(
        Bucket=bucket名称, Key='static/gopher.mp4')   # This action initiates a multipart upload and returns an upload ID
    print(response)
    part_no = 1     # 用于标识分片上传时的数据块号,即 PartNumber
    for part_bytes in list_iter('gopher_img'):
        print('upload ID:', response['UploadId'])
        part = client.upload_part(
            Body=part_bytes,
            Bucket=bucket名称,
            Key='static/gopher.mp4',
            PartNumber=part_no,     # 这个号要唯一,不唯一的话会把前面相同的PartNumber数据覆盖掉
            UploadId=response['UploadId'],
        # 每个 PartNumber 和 ETag 要对应起来
        part_info['Parts'].append({
            'PartNumber': part_no,
            'ETag': part['ETag']
        part_no += 1
    print('part_info:', part_info)
    # Completes a multipart upload by assembling previously uploaded parts. 告诉 AWS S3 已经分片上传完了
    complete_rsp = client.complete_multipart_upload(Bucket=bucket名称,
                                                    Key='static/gopher.mp4',
                                                    UploadId=response['UploadId'],
                                                    MultipartUpload=part_info)
    print('complete_rsp:', complete_rsp)
create_multipart_upld()
输出结果:
{'ResponseMetadata': {'RequestId': 'NVDSJHCASJD', 'HostId': 'MCDCSNDSNAnvdsahnvdasjk', 'HTTPStatusCode': 200, 'HTTPHeaders': {'x-amz-id-2': 'aJGYwJy7UhP/PtFW/OprgKvLxDMi9fUZJuvR2925pnzvk=', 'x-amz-request-id': 'NVDSJHCASJD', 'date': 'Fri, 02 Jul 2021 15:22:52 GMT', 'transfer-encoding': 'chunked', 'server': 'AmazonS3'}, 'RetryAttempts': 0}, 'Bucket': 'bucket-test', 'Key': 'static/gopher.mp4', 'UploadId': '5GuYO83ZlEkhPzApxM49nxvdpvNGF3AQkG0FZ..ALMMpoZGm8KaFBVZOf2qZWY3PGBRgDXZDZXUy_tiNNYeBUOpuUbIm_meupByUIZTdzy4CYkiy0CXKrDf1_lKeGoiv'}
upload ID: 5GuYO83ZlEkhPzApxM49nxvdpvNGF3AQkG0FZ..ALMMpoZGm8KaFBVZOf2qZWY3PGBRgDXZDZXUy_tiNNYeBUOpuUbIm_meupByUIZTdzy4CYkiy0CXKrDf1_lKeGoiv
upload ID: 5GuYO83ZlEkhPzApxM49nxvdpvNGF3AQkG0FZ..ALMMpoZGm8KaFBVZOf2qZWY3PGBRgDXZDZXUy_tiNNYeBUOpuUbIm_meupByUIZTdzy4CYkiy0CXKrDf1_lKeGoiv
upload ID: 5GuYO83ZlEkhPzApxM49nxvdpvNGF3AQkG0FZ..ALMMpoZGm8KaFBVZOf2qZWY3PGBRgDXZDZXUy_tiNNYeBUOpuUbIm_meupByUIZTdzy4CYkiy0CXKrDf1_lKeGoiv
upload ID: 5GuYO83ZlEkhPzApxM49nxvdpvNGF3AQkG0FZ..ALMMpoZGm8KaFBVZOf2qZWY3PGBRgDXZDZXUy_tiNNYeBUOpuUbIm_meupByUIZTdzy4CYkiy0CXKrDf1_lKeGoiv
upload ID: 5GuYO83ZlEkhPzApxM49nxvdpvNGF3AQkG0FZ..ALMMpoZGm8KaFBVZOf2qZWY3PGBRgDXZDZXUy_tiNNYeBUOpuUbIm_meupByUIZTdzy4CYkiy0CXKrDf1_lKeGoiv
part_info: {'Parts': [{'PartNumber': 1, 'ETag': '"3e3d3bae6867b8d207cae1974be3e"'}, {'PartNumber': 2, 'ETag': '"92720cb8294ee04961345f3b664d7"'}, {'PartNumber': 3, 'ETag': '"cc20868db2f8c8c4a6aa499340e0c"'}, {'PartNumber': 4, 'ETag': '"e1bee9034f163677e5ac917576dc7"'}, {'PartNumber': 5, 'ETag': '"b3cd45be65e828debf0d635e75a46"'}]}
complete_rsp: {'ResponseMetadata': {'RequestId': 'B9TJF3EZZ8GSDV2V', 'HostId': 'g7r9/b1OQ8kPLoiDMlKbDREkoRapcDD+zsUJSf4NvlchxT2sS2xHxc42MyJO5ZlcAQ=', 'HTTPStatusCode': 200, 'HTTPHeaders': {'x-amz-id-2': 'g7r9/b1OQ8kPLoiDMlKbqbE51X9iJDRapcDD+zsUJSf4NvlchxT2sS2xHxc42MyJO5ZlcAQ=', 'x-amz-request-id': 'B9TJF3EZZ8GSDV2V', 'date': 'Fri, 02 Jul 2021 15:23:08 GMT', 'content-type': 'application/xml', 'transfer-encoding': 'chunked', 'server': 'AmazonS3'}, 'RetryAttempts': 0}, 'Location': 'https://bucket-test.s3.cn-northwest-1.amazonaws.com.cn/static%2Fgopher.mp4', 'Bucket': 'bucket-test', 'Key': 'static/gopher.mp4', 'ETag': '"2b287762a4300abda18268e1151c83e9-5"'}
create_multipart_upload 参考链接:
upload_part 参考链接:
complete_multipart_upload 参考链接: