【问题标题】:python azure blob storage md5 check fails on blob upload using put_block_blob_from_pathpython azure blob 存储 md5 检查使用 put_block_blob_from_path 上传 blob 失败
【发布时间】:2016-04-27 03:18:59
【问题描述】:

我正在尝试使用 python sdk 将 blob 上传到 azure blob 存储。我想在上传后通过 MD5 哈希在服务器端进行验证。

代码如下:

blob_service.put_block_blob_from_path(
        container_name='container_name',
        blob_name='upload_dir/'+object_name,
        file_path=object_name,
        content_md5=object_md5Hash
)

但我收到此错误:

AzureHttpError: The MD5 value specified in the request did not match with the MD5 value calculated by the server.

文件约为 200mb,错误会立即抛出。不上传文件。所以我怀疑它可能会将提供的哈希与第一个块的哈希或其他东西进行比较。

有什么想法吗?

【问题讨论】:

    标签: python azure hash md5 azure-blob-storage


    【解决方案1】:

    这是一种 SDK 错误,我们应该抛出更好的错误消息而不是点击服务,但验证必须分块的大型上传内容根本不起作用。 x_ms_blob_content_md5 将存储 md5,但服务不会对其进行验证。这是你可以在下载时做的事情。 content_md5 由服务器验证特定请求的正文,但由于有多个带有分块 blob 的请求,它永远不会工作。

    所以,如果 blob 足够小(低于 BLOB_MAX_DATA_SIZE)可以放入单个请求中,content_md5 就可以正常工作。否则,如果您认为您可能想使用 HTTP 下载并在下载时验证它,我会简单地建议使用 HTTPS 并将 MD5 存储在 x_ms_blob_content_md5 中。 HTTPS 已经为网络上的位翻转等提供了验证,因此使用它进行上传/下载会做很多事情。如果由于某种原因无法使用 HTTPS 上传/下载,您可以考虑使用 put 块和 put 块列表 API 自己对 blob 进行分块。

    仅供参考:在未来的版本中,我们确实打算在库本身中为单个 put 和 chunked 操作添加自动 MD5 计算,这将完全解决这个问题。对于下一个版本,如果为分块下载指定 content_md5,我们将添加改进的错误消息。

    【讨论】:

    • 感谢您的回答。为什么不让它在上传完成后验证整个 blob?当您不能将它用于必须分块的 blob 时,包含该参数 (content_md5) 似乎不明智。 Re https,你能指出任何显示如何做到这一点的资源吗?谢谢!
    • Https 默认是开启的,但是你可以在使用 'protocol' 参数设置 blob 服务时显式发送它。如果整个 blob 上传后是分块完成的,该服务没有任何东西可以验证它。由于通用 HTTP 协议,内容 MD5 仅用于当前请求正文。因此,当它可以由 lib 实现(或者如果您想使用 put 块手动实现它)时,每个块的 MD5 是正确的解决方案。
    【解决方案2】:

    我查看了 Azure Blob 存储 SDK 的函数 put_block_blob_from_path 的源代码。功能评论中对案例进行了说明,请看下方内容并参考https://github.com/Azure/azure-storage-python/blob/master/azure/storage/blob/blobservice.py

    content_md5

    可选。 blob 内容的 MD5 哈希值。此哈希用于 在传输过程中验证 blob 的完整性。当这个头 指定时,存储服务检查已到达的哈希 与发送的那个。如果两个哈希不匹配,则 操作将失败,错误代码为 400(错误请求)。

    【讨论】:

      【解决方案3】:

      我认为这里发生了两件事。

      • SDK 中的错误 - 我相信您已经发现了 SDK 中的错误。我在 Github 上查看了这个函数的源代码,我发现当一个大的 blob 以块的形式上传时,SDK 首先尝试创建一个空的块 blob。对于块 blob,这不是必需的。当它创建空块 blob 时,它不发送任何数据。但是您正在设置 content-md5,SDK 会将您发送的 content-md5 与空内容的 content-md5 进行比较,因为它们不匹配,所以会出现错误。

      为了临时解决问题,请修改blobservice.py中的源代码并注释掉以下代码行:

          self.put_blob(
              container_name,
              blob_name,
              None,
              'BlockBlob',
              content_encoding,
              content_language,
              content_md5,
              cache_control,
              x_ms_blob_content_type,
              x_ms_blob_content_encoding,
              x_ms_blob_content_language,
              x_ms_blob_content_md5,
              x_ms_blob_cache_control,
              x_ms_meta_name_values,
              x_ms_lease_id,
          )
      

      我为此在 Github 上创建了一个新问题:https://github.com/Azure/azure-storage-python/issues/99

      • 不正确的用法 - 我注意到您在 content_md5 参数中传递了文件的 md5 哈希值。这对你不起作用。您实际上应该在 x_ms_blob_content_md5 参数中传递 md5 哈希。所以你的电话应该是:
      blob_service.put_block_blob_from_path(
              container_name='container_name',
              blob_name='upload_dir/'+object_name,
              file_path=object_name,
              x_ms_blob_content_md5=object_md5Hash
      )
      

      【讨论】:

      • 这是一个错误,我们应该抛出更好的错误消息而不是点击服务,但是验证必须分块的大型上传的内容根本不起作用。 x_ms_blob_content_md5 将存储 md5,但服务不会验证它。 content_md5 验证特定请求的内容,但由于有多个带有分块的 blob,它永远不会起作用。
      • @EmilyGerner-Microsoft - 我认为错误在于尝试在进行分块上传之前先创建一个空块 blob。恕我直言,这一步完全没有必要,而且会产生问题。例如,如果分块上传失败怎么办。在这种情况下,用户的存储帐户中将有一个零字节 blob。我同意你的 cmets 关于 content_md5/x_ms_blob_content_md5 的看法。
      • 是的,你是对的——这个额外的 put 实际上已经在下一个 lib 版本中被删除了。如果任何访问条件不匹配,则最好缩短上传时间,否则在 put block list 操作上上传后会失败。就像我说的那样,被删除了。 content_md5 仍然会应用到 put block list 操作,尽管这仍然没有意义,因此对于下一个版本,我们还将添加一条错误消息以在上传之前切断该场景。好收获!
      猜你喜欢
      • 2018-09-02
      • 2021-03-31
      • 1970-01-01
      • 1970-01-01
      • 2019-04-06
      • 2014-08-23
      • 2020-03-12
      • 2020-10-19
      • 2013-07-05
      相关资源
      最近更新 更多