簡體   English   中英

boto 獲取 md5 s3 文件

[英]boto get md5 s3 file

我有一個用例,我使用分段上傳將數百個文件上傳到我的 S3 存儲桶。 每次上傳后,我需要確保上傳的文件沒有損壞(基本上檢查數據完整性)。 目前,上傳文件后,我重新下載它,並計算md5上的內容字符串,並將其與比較md5本地文件。 所以像:

conn = S3Connection('access key', 'secretkey')
bucket = conn.get_bucket('bucket_name')
source_path = 'file_to_upload'
source_size = os.stat(source_path).st_size

mp = bucket.initiate_multipart_upload(os.path.basename(source_path))
chunk_size = 52428800
chunk_count = int(math.ceil(source_size / chunk_size))

for i in range(chunk_count + 1):
   offset = chunk_size * i
   bytes = min(chunk_size, source_size - offset)
   with FileChunkIO(source_path, 'r', offset=offset, bytes=bytes) as fp:
       mp.upload_part_from_file(fp, part_num=i + 1, md5=k.compute_md5(fp, bytes))
mp.complete_upload()
    
obj_key = bucket.get_key('file_name')
print(obj_key.md5) #prints None
print(obj_key.base64md5) #prints None

content = bucket.get_key('file_name').get_contents_as_string()
# compute the md5 on content

這種方法很浪費,因為它使帶寬使用量加倍。 我試過

bucket.get_key('file_name').md5 
bucket.get_key('file_name').base64md5 

但都返回無。

有沒有其他方法可以在不下載整個東西的情況下實現md5

是的
使用bucket.get_key('file_name').etag[1 :-1]
這樣就可以在不下載其內容的情況下獲取密鑰的 MD5。

使用 boto3,我使用head_object來檢索 ETag。

import boto3
import botocore

def s3_md5sum(bucket_name, resource_name):
    try:
        md5sum = boto3.client('s3').head_object(
            Bucket=bucket_name,
            Key=resource_name
        )['ETag'][1:-1]
    except botocore.exceptions.ClientError:
        md5sum = None
        pass
    return md5sum

自 2016 年以來,無需任何其他對象檢索即可執行此操作的最佳方法是在 PutObject 請求期間提供--content-md5參數。 然后,AWS 將驗證提供的 MD5 是否與其計算的 MD5 匹配。 這也適用於分段上傳和大於 5GB 的對象。

來自知識中心的示例調用:

aws s3api put-object --bucket awsexamplebucket --key awsexampleobject.txt --body awsexampleobjectpath --content-md5 examplemd5value1234567== --metadata md5checksum=examplemd5value1234567==

https://aws.amazon.com/premiumsupport/knowledge-center/data-integrity-s3/

您可以在不下載文件的情況下從e_tag屬性恢復md5 ,如下所示:

boto3.resource('s3').Object(<BUCKET_NAME>, file_path).e_tag[1 :-1]

然后使用這個函數來比較經典的s3 文件:

def md5_checksum(file_path):
    m = hashlib.md5()
    with open(file_path, 'rb') as f:
        for data in iter(lambda: f.read(1024 * 1024), b''):
            m.update(data)
    return m.hexdigest()

或者這個函數用於多部分文件:

def etag_checksum(file_path, chunk_size=8 * 1024 * 1024):
    md5s = []
    with open(file_path, 'rb') as f:
        for data in iter(lambda: f.read(chunk_size), b''):
            md5s.append(hashlib.md5(data).digest())
    m = hashlib.md5("".join(md5s))
    return '{}-{}'.format(m.hexdigest(), len(md5s))

最后使用此函數在兩者之間進行選擇:

def md5_compare(file_path, s3_file_md5):
    if '-' in s3_file_md5 and s3_file_md5 == etag_checksum(file_path):
        return True
    if '-' not in s3_file_md5 and s3_file_md5 == md5_checksum(file_path):
        return True
    print("MD5 not equals for file " + file_path)
    return False

歸功於: https : //zihao.me/post/calculating-etag-for-aws-s3-objects/

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM