Warning: file_get_contents(/data/phpspider/zhask/data//catemap/0/amazon-s3/2.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
对于大于5GB的文件,计算Amazon-S3 Etag的算法是什么?_Amazon S3_S3cmd - Fatal编程技术网

对于大于5GB的文件,计算Amazon-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。我认为破折号后面的数字是多

上传到AmazonS3的小于5GB的文件有一个ETag,它只是文件的MD5散列,这使得检查本地文件是否与您在S3上放置的文件相同变得容易

但如果您的文件大于5GB,则Amazon会以不同的方式计算ETag

例如,我将一个5970150664字节的文件分380个部分进行了多部分上传。现在S3显示其ETag为
6bcf86bed8807b8e78f0fc6e0a53079d-380
。我的本地文件的md5哈希值为702242d3703818ddefe6bf7da2bed757。我认为破折号后面的数字是多部分上传中的部分数量

我还怀疑新的ETag(在破折号之前)仍然是一个MD5散列,但是在多部分上传的过程中包含了一些元数据

有人知道如何使用与Amazon S3相同的算法计算ETag吗?

没有


到目前为止,还没有解决方案来匹配本地文件的普通文件ETag和多部分文件ETag以及MD5。

不确定是否有帮助:

我们目前正在做一个丑陋的(但到目前为止有用的)黑客来修复多部分上传文件中错误的ETag,这包括对bucket中的文件应用更改;这将从Amazon触发md5重新计算,将ETag更改为与实际md5签名匹配

就我们而言:

文件:bucket/Foo.mpg.gpg

  • ETag获得:“3f92dffef0a11d175e60fb8b958b4e6e-2”
  • 对文件做些什么(重命名它,添加一个元数据,比如一个假头,等等)
  • 获得的Etag:“c1d903ca1bb6dc68778ef21e74cc15b0”

  • 我们不知道算法,但是既然我们可以“修复”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
      aws s3 cp
      上传,则您最有可能拥有8MB的chunksize。根据,这是默认值
    • 如果bucket启用了服务器端加密(SSE),ETag将不会是MD5校验和(请参阅)。但是,如果您只是尝试验证上传的部分是否与您发送的部分匹配,则可以使用
      Content-MD5
      标题和
    • macOS上的
      md5
      只输出校验和,而Linux/brew上的
      md5sum
      也输出文件名。您需要去掉它,但我确信有一些选项可以只输出校验和。您不必担心空格,因为
      xxd
      将忽略它
    代码链接

    • 我写的一个要点是用一个字母写的
    • 该项目位于

    相同的算法,java版本: (BaseEncoding、Hasher、Hashing等来自

    /**
    *为来自多部分上载的对象生成校验和

    *

    *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实现中的自述文件中复制):

  • md5块
  • 将md5字符串放在一起
  • 将glob转换为二进制
  • md5全局块md5s的二进制文件
  • 将“-Number_of_chunks”追加到二进制文件的md5字符串的末尾

  • 下面是计算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);
    }否则