对于大于5GB的文件,计算Amazon-S3 Etag的算法是什么?
上传到AmazonS3的小于5GB的文件有一个ETag,它只是文件的MD5散列,这使得检查本地文件是否与您在S3上放置的文件相同变得容易 但如果您的文件大于5GB,则Amazon会以不同的方式计算ETag 例如,我将一个5970150664字节的文件分380个部分进行了多部分上传。现在S3显示其ETag为对于大于5GB的文件,计算Amazon-S3 Etag的算法是什么?,amazon-s3,s3cmd,Amazon S3,S3cmd,上传到AmazonS3的小于5GB的文件有一个ETag,它只是文件的MD5散列,这使得检查本地文件是否与您在S3上放置的文件相同变得容易 但如果您的文件大于5GB,则Amazon会以不同的方式计算ETag 例如,我将一个5970150664字节的文件分380个部分进行了多部分上传。现在S3显示其ETag为6bcf86bed8807b8e78f0fc6e0a53079d-380。我的本地文件的md5哈希值为702242d3703818ddefe6bf7da2bed757。我认为破折号后面的数字是多
6bcf86bed8807b8e78f0fc6e0a53079d-380
。我的本地文件的md5哈希值为702242d3703818ddefe6bf7da2bed757。我认为破折号后面的数字是多部分上传中的部分数量
我还怀疑新的ETag(在破折号之前)仍然是一个MD5散列,但是在多部分上传的过程中包含了一些元数据
有人知道如何使用与Amazon S3相同的算法计算ETag吗?没有
到目前为止,还没有解决方案来匹配本地文件的普通文件ETag和多部分文件ETag以及MD5。不确定是否有帮助: 我们目前正在做一个丑陋的(但到目前为止有用的)黑客来修复多部分上传文件中错误的ETag,这包括对bucket中的文件应用更改;这将从Amazon触发md5重新计算,将ETag更改为与实际md5签名匹配 就我们而言: 文件:bucket/Foo.mpg.gpg
我们不知道算法,但是既然我们可以“修复”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”以获得ETag,因为有3个部分
注释
- 如果您使用via
上传,则您最有可能拥有8MB的chunksize。根据,这是默认值aws s3 cp
- 如果bucket启用了服务器端加密(SSE),ETag将不会是MD5校验和(请参阅)。但是,如果您只是尝试验证上传的部分是否与您发送的部分匹配,则可以使用
标题和Content-MD5
- macOS上的
只输出校验和,而Linux/brew上的md5
也输出文件名。您需要去掉它,但我确信有一些选项可以只输出校验和。您不必担心空格,因为md5sum
将忽略它xxd
- 我写的一个要点是用一个字母写的
- 该项目位于
/**
*为来自多部分上载的对象生成校验和
*
*AWS S3规范:标识新创建对象数据的实体标记。具有不同对象数据的对象将具有不同的实体标记。实体标记是不透明字符串。实体标记可能是也可能不是对象数据的MD5摘要。如果实体标记不是对象数据的MD5摘要,则它将包含一个或多个非十六进制c字符和/或将由少于32或多于32个十六进制数字组成。
*算法遵循AWS S3实现:https://github.com/Teachnova/s3md5
*/
私有静态字符串calculateChecksumForMultipartUpload(列表md5s){
StringBuilder StringBuilder=新的StringBuilder();
用于(字符串md5:md5s){
stringBuilder.append(md5);
}
字符串hex=stringBuilder.toString();
字节raw[]=BaseEncoding.base16().decode(hex.toUpperCase());
Hasher-Hasher=Hashing.md5().newHasher();
hasher.putBytes(原始);
字符串摘要=hasher.hash().toString();
返回摘要+“-”+md5s.size();
}
在上面的回答中,有人问是否有办法为大于5G的文件获取md5
对于获取MD5值(对于大于5G的文件),我可以给出一个答案,要么手动将其添加到元数据中,要么使用一个程序进行上传,从而添加信息
例如,我使用s3cmd上传了一个文件,它添加了以下元数据
$ aws s3api head-object --bucket xxxxxxx --key noarch/epel-release-6-8.noarch.rpm
{
"AcceptRanges": "bytes",
"ContentType": "binary/octet-stream",
"LastModified": "Sat, 19 Sep 2015 03:27:25 GMT",
"ContentLength": 14540,
"ETag": "\"2cd0ae668a585a14e07c2ea4f264d79b\"",
"Metadata": {
"s3cmd-attrs": "uid:502/gname:staff/uname:xxxxxx/gid:20/mode:33188/mtime:1352129496/atime:1441758431/md5:2cd0ae668a585a14e07c2ea4f264d79b/ctime:1441385182"
}
}
它不是使用ETag的直接解决方案,但它是一种以您可以访问的方式填充所需元数据(MD5)的方法。如果有人在没有元数据的情况下上载文件,它仍然会失败。
$ aws s3api head-object --bucket xxxxxxx --key noarch/epel-release-6-8.noarch.rpm
{
"AcceptRanges": "bytes",
"ContentType": "binary/octet-stream",
"LastModified": "Sat, 19 Sep 2015 03:27:25 GMT",
"ContentLength": 14540,
"ETag": "\"2cd0ae668a585a14e07c2ea4f264d79b\"",
"Metadata": {
"s3cmd-attrs": "uid:502/gname:staff/uname:xxxxxx/gid:20/mode:33188/mtime:1352129496/atime:1441758431/md5:2cd0ae668a585a14e07c2ea4f264d79b/ctime:1441385182"
}
}
该算法的字面意思是(从python实现中的自述文件中复制):
下面是计算ETag的PHP版本:
函数calculate\u aws\u etag($filename,$chunksize){
/*
说明:
-计算S3服务上使用的Amazon AWS ETag
输入:
-$filename:要检查的文件的路径
-$chunksize:块大小(以MB为单位)
输出:
-ETag(字符串)
*/
$chunkbytes=$chunksize*1024*1024;
if(文件大小($filename)<$chunkbytes){
返回md5_文件($filename);
}否则