我需要在亚马逊S3上使用boto,从同一个存储桶移动大型文件(> 5GB)。为此,我需要使用multipart API,它不使用md5求和的etags。
虽然我认为(只有98%肯定)我的代码是正确的,但我想在删除原始代码之前验证新副本是否已损坏。但是我找不到任何方法,除了下载两个对象并在本地比较它们,对于5GB +文件是一个相当长的过程。
对于记录,下面是我用boto复制大文件的代码,也许这可以帮助某人。如果我的问题没有很好的解决方案,也许有人会发现错误并阻止我破坏数据。
import boto
copy_size = 1000000000 #1e9
bucket_name = 'mybucket'
orig_key_name = 'ABigFile'
dest_key_name = 'ABigFile.clone'
s3 = boto.connect_s3()
mybucket = s3.get_bucket(bucket_name)
key = mybucket.get_key(orig_key_name)
mp = mybucket.initiate_multipart_upload(dest_key_name) #keyname
print 'key size: ', key.size
count = 1
start = 0
end = -1
while end < key.size-1:
print 'count: ', count
start = end + 1
end = min( key.size -1 , start + copy_size )
mp.copy_part_from_key(bucket_name, orig_key_name, count , start, end )
count+=1
mp.complete_upload()
此代码仅适用于原始密钥大小&gt; = 5368709121字节。
答案 0 :(得分:1)
您应该能够在数据流上计算SHA-1哈希值(see this SO thread用于C ++代码,这可以为python方法提供提示)。通过将散列数据流重定向到等效的/dev/null
,您应该能够比较两个文件的SHA-1哈希,而无需先在本地下载它们。
答案 1 :(得分:0)
如果不知道AWS如何计算分段上传的etag,就无法做任何你想做的事情。如果您有对象的本地副本,则可以计算要在本地对象上复制的每个部分的md5,并将其与每个mp.copy_part_from_key()返回的键中的etag进行比较。听起来你没有本地对象。
您还有一个隐藏在boto中的小问题,可能会或可能不会导致您在极少数情况下丢失数据。如果你看一下boto源代码,你会注意到mp.complete_upload()函数在上传时实际上没有使用AWS返回的任何部分的任何etags。当你使用multipart_complete时,它实际上会自己创建一个全新的多部分列表,并从S3获取一个新的部件和etags列表。这是有风险的,因为最终的一致性,列表可能会也可能不完整。理想情况下,multipart_complete()应该使用每个远程副本返回的etags和part信息是完全安全的。这是亚马逊在其文档中推荐的内容(请参阅Multipart Upload Listings下的注释)。
也就是说,如果确认两个对象的文件大小相同,则不太可能出现问题。我认为最糟糕的情况是部件未列在分段上传列表中。列出的部分本身永远不应该是错误的。