上传到Amazon S3的小于5GB的文件具有一个ETag,该ETag只是该文件的MD5哈希,这使你很容易检查本地文件是否与你在S3上放置的文件相同。
但是,如果你的文件大于5GB,则Amazon对ETag的计算会有所不同。
例如,我对380个部分的5970150664字节文件进行了分段上传。现在,S3显示它的ETag为6bcf86bed8807b8e78f0fc6e0a53079d-380
。我的本地文件的md5哈希为702242d3703818ddefe6bf7da2bed757
。我认为破折号后的数字是分段上传中的部分数量。
我还怀疑新的ETag(破折号之前)仍然是MD5哈希,但是在分段上传的过程中包含了一些元数据。
有谁知道如何使用与Amazon S3相同的算法来计算ETag?
假设你将一个14MB的文件上传到没有服务器端加密的存储桶中,而部件大小为5MB。计算每个部分对应的3个MD5校验和,即前5MB,后5MB和后4MB的校验和。然后取其串联的校验和。MD5校验和通常以二进制数据的十六进制表示形式打印,因此请确保使用解码后的二进制级联的MD5,而不是ASCII或UTF-8编码级联的MD5。完成后,添加连字符和零件数量以获取ETag。
以下是从控制台在Mac OS X上执行此操作的命令:
$ dd bs=1m count=5 skip=0 if=someFile | md5 >>checksums.txt
5+0 records in
5+0 records out
5242880 bytes transferred in 0.019611 secs (267345449 bytes/sec)
$ dd bs=1m count=5 skip=5 if=someFile | md5 >>checksums.txt
5+0 records in
5+0 records out
5242880 bytes transferred in 0.019182 secs (273323380 bytes/sec)
$ dd bs=1m count=5 skip=10 if=someFile | md5 >>checksums.txt
2+1 records in
2+1 records out
2599812 bytes transferred in 0.011112 secs (233964895 bytes/sec)
此时,所有校验和都在中checksums.txt
。要连接它们并解码十六进制并获得批次的MD5校验和,只需使用
$ xxd -r -p checksums.txt | md5
现在有3个部分,请附加“ -3”以获取ETag。
笔记
aws s3 cp
则很可能具有8MB的块大小。根据docs,这是默认设置。Content-MD5
标题,S3会为你进行比较。md5
在macOS上仅写出校验和,但md5sum
在Linux / brew上也输出文件名。你将需要剥离它,但是我敢肯定有一些选项仅输出校验和。你无需担心空格,因为xxd
它将忽略它。代码链接
有趣的发现,希望亚马逊不会更改它,因为它是未记录的功能
好点子。根据HTTP规范,ETag完全由他们决定,唯一的保证是他们不能为更改的资源返回相同的ETag。我猜测虽然更改算法没有太多优势。
有没有一种方法可以从etag中计算出“零件尺寸”?
“计算”不,“猜测”。如果ETag以“ -4”结尾,则您知道有四个部分,但最后一个部分的大小可小至1个字节,最大为该部分的大小。因此,将文件大小除以部分数可以得出一个估计值,但是当部分数很小(例如-2)时,就很难猜测了。如果您有多个使用相同零件尺寸上传的文件,则还可以查找相邻的零件计数,例如-4和-5并缩小零件尺寸的范围,例如,在-2处为1.9MB,在-处为2.1MB 3表示部件大小为2MB正负100KB。
我认为依靠AWS的内部实现是不明智的,只要它们不会将哈希算法特别暴露为合同(如果它会影响应用程序的正确性)(通常在验证数据完整性时就是这种情况) 。