AWS S3 大文件分片上傳


分段上傳允許上傳單個對象作為一組分段。每個分段都是對象數據的連續部分。您可以獨立上傳以及按任意順序上傳這些對象分段。如果任意分段傳輸失敗,可以重新傳輸該分段且不會影響其他分段。上傳完所有的數據元分段后,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 參考鏈接:
 
 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM