【问题标题】:Amazon S3 huge file integrityAmazon S3 大文件完整性
【发布时间】:2016-06-16 07:58:34
【问题描述】:

我很困惑如何检查上传到 Amazon S3 的文件的完整性。我可以看到一些关于此的 StackOverflow 问题,但它们似乎使用较旧的 API,看起来与我现在使用的非常不同,它们指的是包含 md5 的 E-Tag,这似乎不再有效,或者对于超过 5GB 的文件。

所以,基本上,我使用 PHP 上传大文件(其中一些超过 70GB),使用 MultipartUploader 和 Try/Catch,如下所示:

        try {
            $result = $uploader->upload();
        } catch (MultipartUploadException $e) {
            $uploader = new MultipartUploader($s3, $file, array(
                'state' => $e->getState()
            ));
        }

我遇到了几个类似这样的错误:

将部分上传到分段上传时发生异常。以下部分有错误: - 第 7729 部分:在 ... 上执行“UploadPart”时出错导致500 Internal Server Error 响应: InternalError我们遇到了一个内部错误。恳求(截断...) InternalError(服务器):我们遇到了内部错误。请再试一次。 - InternalError我们遇到了一个内部错误。请重试。

第 660 部分:在“...”上执行“UploadPart”时出错; AWS HTTP 错误:cURL 错误 56:SSL 读取:错误:00000000:lib(0):func(0):reason(0),errno 104(请参阅http://curl.haxx.se/libcurl/c/libcurl-errors.html)(服务器):100 继续 -

第 6542 部分:在“...”上执行“UploadPart”时出错; AWS HTTP 错误:cURL 错误 52:来自服务器的空回复(请参阅 http://curl.haxx.se/libcurl/c/libcurl-errors.html

所有这些似乎都落入了“MultipartUploadException”的Catch,它试图从当前状态再次上传。

但我仍然担心上传文件的完整性,所以我想知道如何检查。当我查看 S3 管理控制台时,一个文件的属性显示:

ETag:ba66d1235f954f28366ddc0a7efcb295-1609

但是当我在本地执行“md5sum”时,我得到了完全不同的东西:

fa693af7341c6c83e525ebc6b95422ea

这是否意味着上传的文件已损坏?

如果不是,如何检查上传文件的完整性?

【问题讨论】:

    标签: php amazon-web-services amazon-s3


    【解决方案1】:

    在多部分上传时,etag 的计算方法是采用每个部分的 md5 哈希的二进制编码¹,将它们连接在一起,对其进行 md5,对结果进行十六进制编码,然后附加 - 后跟部分的数量.

    如果您知道上传部分的大小,则可以计算给定文件的正确多部分 etag 值。我编写了一个 s3 分段上传器(未发布),它预先计算了这个值并将其存储为 x-amz-meta-expect-etag 以供以后手动或机器验证。在某个地方,我可能有一个独立的实用程序,可以在事后从本地文件中计算出来。我去找找。

    您的谨慎是正确的,但您的担忧可能在很大程度上是没有根据的。如果您使用的库利用了多部分 API 中内置的故障保护,那么您应该很好:

    每个部分在上传时都应发送一个Content-MD5 标头,其中包含该部分的 md5 哈希的 base64 编码。如果这在请求中存在,S3 将故意不接受该部分,因为数据被认为在传输中已损坏。

    每个部分在上传时都会收到一个响应,其中包含该部分的 etag,其中包含该部分的 md5,以十六进制表示。代码应该验证该值。

    然后,S3 要求您组装“完成”请求以在所有部分完成后完成上传。在此请求中,您包含各个部分的所有 etag,您应该在上传过程中在本地维护这些 etag。 (有一种方法可以向 S3 询问列表,但那是为了交叉检查,并且该数据不应该用于实际组装完整的多部分上传请求。如果这些值不像 S3 认为的那样,则请求失败,并且该对象从不存在于存储桶中。

    因此,如果操作得当,S3 分段上传在确保数据完整性方面非常出色……它会非常努力地不让您弄错并创建不完美的对象。您应该审核您正在使用的库的代码,以验证它们是否执行了这些操作。如果他们这样做,你应该很好。在这么写的一个内部系统的早期版本中,我实际上在每次分段上传后使用curl 'https://{pre-signed-url}' | md5sum 来验证。它以这种方式运行了几年,当使用所有编写的代码使用提供的保护措施直接与 S3 服务(无 SDK)对话时,我确实从未设法创建了一个糟糕的分段上传通过多部分 API。


    ¹一个 md5 哈希是一个 128 位的值。它的“二进制编码”(不是一个精确的术语,因为它不是真正的“编码”,只是“原始”)是一个 16 字节的值,其中每个字节包含一个 0-255 范围内的值。如果将 md5 哈希的字节简单地转换为字符串,则许多字节会导致无法打印的字符...因此,常见的表示形式是十六​​进制,这会导致 32 字节 (128 ÷ 4) 的输出(使用字符 0 -9, a-f) 因为每个十六进制字符只编码 4 位......或者在 base64 中不太常见(字符 0-9A-Za-z+/=),你得到 24 个字节(128 ÷ 6,四舍五入到下一个倍数4) 的输出,因为每个字符编码 6 位。你不连接 32 字节的十六进制编码,你需要每个部分的 md5 的原始二进制版本,每个部分是 16 个字节。

    【讨论】:

    • 你好。非常感谢您的回答。很遗憾他们没有为整个文件提供完整的 MD5 和。将我的文件分成几部分并计算每个文件的 MD5 总和会有点过头了……但是,我刚刚下载了 2 个最大的文件,计算了 MD5 并且它与本地总和相匹配。非常亲切的问候,感谢您的回复。
    • 创建校验和是 CPU 密集型的。如果您尝试计算 20 GB 视频文件的校验和,您就会明白我的意思了。
    【解决方案2】:

    上传到 S3 时,保证复制保真度(完美传输)的唯一方法是使用校验和。为了便于管理,AWS 允许您将文件分成几部分,计算校验和,然后将该校验和作为签名的一部分发送到“Content-Md5”标头中。

    您不能假设您发布到 S3 的内容没有错误地存储。

    AWS PUT API 请求返回 500 或其他错误的情况并不少见。这已记录在案,这也是 AWS 要求您在这种情况下重试的原因之一。

    AWS S3 分段上传的巨大好处主要是复制保真度、上传恢复以防出错(您只需重试部分,而不是整个文件),如果您有一个非常胖的管道,上传的并行化以提高吞吐量。

    https://github.com/TTLabs/EvaporateJS 有一个非常流行的基于浏览器的实现,因为适用于浏览器的 AWS JavaScript 开发工具包不支持对除文本 mime 类型(没有像视频、图像、音乐这样的二进制文件)之外的任何内容的分段上传中的校验和.

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2018-04-12
      • 1970-01-01
      • 2018-03-14
      • 2011-07-05
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多