![](/img/trans.png)
[英]How to programmatically get the MD5 Checksum of Amazon S3 file using boto
[英]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.