如何检查 Azure 存储 BLOB 文件是否已成功上传?

9

我使用AzCopy工具将一个大小约为9GB的zip压缩文件上传到Azure Storage BLOB容器中,现在想要检查它是否正确。我可以从Azure门户获取该文件的“CONTENT-MD5”值。那么我需要在我的本地计算出这个值,是吗?除了下载此文件之外,还有其他检查有效性的方法吗?这个文件是使用没有MD5哈希算法的7zip实用程序进行归档的。

3个回答

12
以下是关于Azure的MD5验证和属性设置的工作原理。
在服务器端,Azure会计算每个上传文件的MD5值。
如果该上传文件恰好代表一个“完整文件”(完整的Blob——PutBlob是其内部名称),则它还将免费为您存储该MD5值在Blob属性中。它也会将其计算出来的值作为响应HTTP标头返回。
如果您在上传时传递了“Content-MD5”标头,则Azure(服务器)还将根据该值验证上传,并在不匹配时失败上传。同样,它会为您存储MD5值。
如果您不是在“一次性”上传中上传“完整文件”,则真正的奇怪之处就出现了。
如果您的文件大于 client.SingleBlobUploadThresholdInBytes(通常为32MB,C#256MB),则 Azure 客户端将会“将您的上传拆分成4MB块 [max用PutBlock上传每个块,然后使用PutBlockList方法提交所有块。”可能会并行上传块。Azure自身对任何单个上传都有100MB的硬限制,因此您无法将client.SingleBlobUploadThresholdInBytes调整到此其他限制之上(更新:可能已更改为5GB)。您必须将上传拆分为每个块4MB的“块”(片段)。 (不相关的副作用是,在Azure中,“块”是可更改/可更新的,但不是单个字节。 “一次性”上传(最高限度为该限制)基本上包含一个大的“块”,因此基本上是不变的。 如果您进行多个块上传,则可以更改该blob中的单个块)。
如果您正在以“块”方式上传,Azure仅支持在上传时让服务器“验证”每个块的MD5值。因此,如果您将客户端参数设置为setComputeMd5(true)(Java)或validate_content = true(Python),它将在上传每个4MB块时计算其MD5,并将其传递以进行验证。文档说这在使用HTTPS时“不需要”,因为HTTPS还会对相同字节计算校验和并将其与传输一起包括,所以有些冗余。每个块的CONTENT-MD5被称为事务性(类似于短暂的)MD5。似乎一旦验证了该块,就会被丢弃。
这意味着,在使用“分块”上传的文件上传结束时,Azure 中不会设置 CONTENT-MD5 属性,因为它需要应用于“整个 blob”。Azure 不知道所有块按顺序组合在一起的 MD5 值应该是什么(它只处理随着数据传入而产生的每个传输的 MD5 值),并且在最后将所有块组合在一起时不会重新计算全局值。我们所知道的是,它实际上并没有将它们“组合”在一起,而只是在内部将块链接到彼此。这意味着,“有时候”当您使用相同的客户端调用进行上传时,它将设置 CONTENT-MD5 属性,有时候则不会(当文件被认为太大时)。
如果我们在上传时对整个文件进行了MD5处理,那么我们还有哪些选项呢?我们不能将其用作特定块的上传头。因此,Azure的PutBlockList命令被更改为接受“另一种”MD5形式,称为x-ms-blob-content-md5。如果使用这个选项,它基本上会设置Azure中blob的CONTENT-MD5属性,并且不会检查或验证它。实际上,如果在Azure中更新blob,则根本不会修改CONTENT-MD5属性,因此它可能过时。您也可以通过事后“设置blob属性”调用来在Azure中设置此属性,在上传后将其设置为任意值而不进行检查。C#客户端具有BlobOption以设置StoreBlobContentMD5,但似乎不允许您提供该值。Java客户端似乎没有此选项,因此在任何情况下都可以手动设置标头来提供它。如果您有任何支持"--put-md5"选项的客户端(例如azcopy),则该选项可能只是设置此属性,适用于大型文件。其他选项是在将字节传递给客户端时计算其MD5并检查是否匹配,并假设它们已经到达(InputStream包装样式)。或者在上传后重新计算文件的MD5(本地),并“希望”客户端读取并上传了与您刚刚读取的相同的字节(它会在每个块中计算事务性MD5和/或HTTPS校验和)。
或者痛苦的选项是:重新下载以验证其MD5是否有效。如果您想以这种方式进行操作,一种“简单”的方法是首先设置Azure CONTENT-MD5属性(参见上文),然后使用Azure客户端执行文件下载。在客户端上,它将在下载时计算md5,将其与azure中“当前设置”的md5进行比较(如果存在于azure中,则作为下载标头发送),如果最终不匹配,则客户端将失败该操作。因此,基本上,Azure支持在客户端验证大型文件的完整文件MD5,但不支持服务器端...或创建一个 Azure function 来执行类似于上传后的客户端验证等效操作。

还有一件类似MD5的事情是Azure支持的:如果您使用指定范围为4MB或更小的“获取blob”,还可以指定x-ms-range-get-content-md5,它将在CONTENT-MD5 HTTP标头中返回该范围的MD5。顺便说一下。


10
「Content-MD5」属性并非由 Azure 存储 Blob 服务实时维护,它实际上是在上传时由 AzCopy 计算,并在 AzCopy 完成上传后设置到目标 blob 上。因此,如果你真的想验证数据完整性,你需要使用带有 /CheckMD5 选项的 AzCopy 下载文件,然后将下载的文件与本地原始文件进行比较。
然而,考虑到 AzCopy 已经尽最大努力保护数据完整性,在你的场景下,强烈不建议执行上述验证步骤,除非数据完整性比性能更重要。

1
您好。正如您所提到的“鉴于AzCopy在传输过程中已经尽最大努力保护数据完整性”,能否详细说明他们用于验证的方法呢?我想在不重新检查MD5的情况下解释这一点。 - Spacez

-2

从PowerShell中,您可以运行以下命令来获取文件的MD5哈希值

Get-FileHash -Path "C:\temp\somefile.zip" -Algorithm MD5

如果您正在使用C#,您也可以使用此代码片段。
using (var md5 = System.Security.Cryptography.MD5.Create())
{
    using (var stream = File.OpenRead(filename))
    {
        return md5.ComputeHash(stream);
    }
}

虽然有用,但这完全没有回答楼主的问题。 - Marcel

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接