如何检查正确上传的 Azure 存储 BLOB 文件?
How to check Azure Storage BLOB file uploaded correctly?
我已使用 AzCopy 实用程序将一个大型 zip 存档上传到 Azure 存储 BLOB 容器,~9GB。现在我想检查它是否正确。我可以从 Azure 门户获取文件的 "CONTENT-MD5" 值。那我这边就得算算了吧?是否有任何其他方法来检查有效性(下载此文件除外)?它是使用 7zip 实用程序存档的,该实用程序没有 MD5 的哈希算法。
您可以从 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);
}
}
每个 real-time blob 内容的 "Content-MD5" 属性 不由 Azure 存储 Blob 服务维护。实际上,它是在上传期间由 AzCopy 计算的,并在 AzCopy 完成上传时设置为目标 blob。因此,如果您真的想验证数据完整性,则必须使用带有 /CheckMD5 选项的 AzCopy 下载文件,然后将下载的文件与本地原始文件进行比较。
但是,鉴于 AzCopy 已尽最大努力在传输过程中保护数据完整性,上述验证步骤可能是多余的,强烈建议不要这样做,除非在您的方案中数据完整性比性能重要得多。
以下是 MD5 验证和 属性 设置如何适用于 Azure。
Azure 在服务器端计算每次上传的 MD5。
如果该上传恰好表示“完整文件”(完整 blob——PutBlob 是内部名称),那么它还会在 blob 属性中“免费”为您存储该 MD5 值。它恰好也 return 它作为响应 HTTP header.
计算的值
如果您在上传“Content-MD5”时传递 header,azure(服务器)也会根据该值验证上传,如果不匹配则上传失败。它再次为您存储 MD5 值。
如果您没有在“一次性”上传中上传“完整文件”,真正的怪异就来了。
如果您的文件大于 client.SingleBlobUploadThresholdInBytes (typically 32MB, 256MB for C#), then Azure client will "break your upload up into 4-MB blocks [max for PutBlock], upload each block with PutBlock, and then commit all blocks with the PutBlockList method." Possibly uploading blocks in parallel. Azure itself has a 100MB hard limit on a single upload of any kind, so you can't adjust client.SingleBlobUploadThresholdInBytes past this other limit (update: might have changed to 5GB)。您被迫将上传拆分为每个 4MB 的“块”(块)。 (不相关的副作用:天蓝色的“块”是 changeable/updateable 但不是单个字节。“一次性”上传(达到该限制)基本上包含一个大“块”,因此本质上是不可变的。如果你去多个块上传,您可以更改该 blob 中的单个块)
如果您以“块”的形式上传,Azure 仅支持让服务器在上传时“验证”每个块的 MD5 值。因此,如果您将客户端的参数设置为 setComputeMd5(true)
(java) 或 validate_content = true
(python),它将在上传时计算每个 4MB 块的 MD5 ,并将其传递以通过块上传进行验证。文档说这“在使用 HTTPS 时不需要”,因为 HTTPS 还会计算相同字节的校验和并将其包含在传输中,因此有点多余。每个块的 CONTENT-MD5 被“称为”事务性(有点像短暂的)MD5。一旦验证了该块,似乎就会被丢弃。
这意味着在使用“分块”上传文件的一天结束时,CONTENT-MD5 属性 将不会在 Azure 中设置,因为它需要申请“整个斑点”。 Azure 不知道所有块的 MD5 按顺序排列在一起的值应该是多少(它只处理 per-transfer MD5,因为数据进来了),而且它不是 re-calculate 全局的最后将所有部分放在一起时。据我们所知,它实际上并没有将它们“放在一起”本身,只是在内部将点块相互链接起来。这意味着当您使用相同的客户端调用上传时,“有时”会设置 CONTENT-MD5 属性,有时则不会(当文件被认为太大时)。
因此,如果我们在上传时拥有整个文件的 MD5,我们还有哪些选择?我们不能将它用作特定块的上传 header。因此,Azure 的 PutBlockList 命令被更改为接受“另一种”形式的 MD5,称为 x-ms-blob-content-md5
。如果您使用它,它基本上会将 blob 的 CONTENT-MD5 属性 设置为 azure,并且不会对其进行检查或验证。事实上,如果您在 azure 中对 blob 进行更新,它根本不会修改 CONTENT-MD5 属性,并且它可能会过时。您还可以在上传后使用 post-hoc“set blob 属性”调用在 Azure 中设置此 属性,这同样会在不检查的情况下将其设置为任意值。 C# 客户端有一个 BlobOption 来设置此 StoreBlobContentMD5
,但似乎不允许您提供该值。 Java 客户端似乎没有它的选项,也许可以设置手动 headers 以在任何一种情况下提供它。如果您有任何客户端带有 azcopy 的“--put-md5”之类的选项,它可能只是为大文件设置此 属性。只有其他选择是在将字节传递给客户端时计算字节的 MD5,并查看是否对齐,并假设它们成功了(包装的 InputStream 样式)。或者 re-compute 上传后文件(本地)的 MD5,并“希望”客户端读取和上传与您刚刚读取的字节相同的字节(它会计算事务性 md5 的 and/or HTTPS 校验和,对于每个块)。
或者痛苦的选择:re-download 验证它的 MD5 是否有效。如果你想这样做,一个“简单”的方法是先设置 azure CONTENT-MD5 属性(见上文),然后使用 azure 客户端执行文件下载。在 client-side 上,它将在下载时计算 md5,将其与 azure 中的“当前设置”进行比较(如果存在于 azure 中,则作为下载 header 发送),客户端将失败如果最后不匹配则执行操作。所以基本上 azure 支持验证 client-side 上大文件的 full-file MD5,但不支持 server-side...或者创建一个 Azure function 来做一个等同于 client-side上传后验证。
Azure 还支持另外一种 MD5 类型的东西:如果你执行一个指定范围为 4MB 或更小的“get blob”,你也可以指定 x-ms-range-get-content-md5
并且它将 return you 那个跑的MD5e 在 CONTENT-MD5 HTTP header 中。 FWIW.
我已使用 AzCopy 实用程序将一个大型 zip 存档上传到 Azure 存储 BLOB 容器,~9GB。现在我想检查它是否正确。我可以从 Azure 门户获取文件的 "CONTENT-MD5" 值。那我这边就得算算了吧?是否有任何其他方法来检查有效性(下载此文件除外)?它是使用 7zip 实用程序存档的,该实用程序没有 MD5 的哈希算法。
您可以从 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);
}
}
"Content-MD5" 属性 不由 Azure 存储 Blob 服务维护。实际上,它是在上传期间由 AzCopy 计算的,并在 AzCopy 完成上传时设置为目标 blob。因此,如果您真的想验证数据完整性,则必须使用带有 /CheckMD5 选项的 AzCopy 下载文件,然后将下载的文件与本地原始文件进行比较。
但是,鉴于 AzCopy 已尽最大努力在传输过程中保护数据完整性,上述验证步骤可能是多余的,强烈建议不要这样做,除非在您的方案中数据完整性比性能重要得多。
以下是 MD5 验证和 属性 设置如何适用于 Azure。
Azure 在服务器端计算每次上传的 MD5。
如果该上传恰好表示“完整文件”(完整 blob——PutBlob 是内部名称),那么它还会在 blob 属性中“免费”为您存储该 MD5 值。它恰好也 return 它作为响应 HTTP header.
计算的值如果您在上传“Content-MD5”时传递 header,azure(服务器)也会根据该值验证上传,如果不匹配则上传失败。它再次为您存储 MD5 值。
如果您没有在“一次性”上传中上传“完整文件”,真正的怪异就来了。
如果您的文件大于 client.SingleBlobUploadThresholdInBytes (typically 32MB, 256MB for C#), then Azure client will "break your upload up into 4-MB blocks [max for PutBlock], upload each block with PutBlock, and then commit all blocks with the PutBlockList method." Possibly uploading blocks in parallel. Azure itself has a 100MB hard limit on a single upload of any kind, so you can't adjust client.SingleBlobUploadThresholdInBytes past this other limit (update: might have changed to 5GB)。您被迫将上传拆分为每个 4MB 的“块”(块)。 (不相关的副作用:天蓝色的“块”是 changeable/updateable 但不是单个字节。“一次性”上传(达到该限制)基本上包含一个大“块”,因此本质上是不可变的。如果你去多个块上传,您可以更改该 blob 中的单个块)
如果您以“块”的形式上传,Azure 仅支持让服务器在上传时“验证”每个块的 MD5 值。因此,如果您将客户端的参数设置为 setComputeMd5(true)
(java) 或 validate_content = true
(python),它将在上传时计算每个 4MB 块的 MD5 ,并将其传递以通过块上传进行验证。文档说这“在使用 HTTPS 时不需要”,因为 HTTPS 还会计算相同字节的校验和并将其包含在传输中,因此有点多余。每个块的 CONTENT-MD5 被“称为”事务性(有点像短暂的)MD5。一旦验证了该块,似乎就会被丢弃。
这意味着在使用“分块”上传文件的一天结束时,CONTENT-MD5 属性 将不会在 Azure 中设置,因为它需要申请“整个斑点”。 Azure 不知道所有块的 MD5 按顺序排列在一起的值应该是多少(它只处理 per-transfer MD5,因为数据进来了),而且它不是 re-calculate 全局的最后将所有部分放在一起时。据我们所知,它实际上并没有将它们“放在一起”本身,只是在内部将点块相互链接起来。这意味着当您使用相同的客户端调用上传时,“有时”会设置 CONTENT-MD5 属性,有时则不会(当文件被认为太大时)。
因此,如果我们在上传时拥有整个文件的 MD5,我们还有哪些选择?我们不能将它用作特定块的上传 header。因此,Azure 的 PutBlockList 命令被更改为接受“另一种”形式的 MD5,称为 x-ms-blob-content-md5
。如果您使用它,它基本上会将 blob 的 CONTENT-MD5 属性 设置为 azure,并且不会对其进行检查或验证。事实上,如果您在 azure 中对 blob 进行更新,它根本不会修改 CONTENT-MD5 属性,并且它可能会过时。您还可以在上传后使用 post-hoc“set blob 属性”调用在 Azure 中设置此 属性,这同样会在不检查的情况下将其设置为任意值。 C# 客户端有一个 BlobOption 来设置此 StoreBlobContentMD5
,但似乎不允许您提供该值。 Java 客户端似乎没有它的选项,也许可以设置手动 headers 以在任何一种情况下提供它。如果您有任何客户端带有 azcopy 的“--put-md5”之类的选项,它可能只是为大文件设置此 属性。只有其他选择是在将字节传递给客户端时计算字节的 MD5,并查看是否对齐,并假设它们成功了(包装的 InputStream 样式)。或者 re-compute 上传后文件(本地)的 MD5,并“希望”客户端读取和上传与您刚刚读取的字节相同的字节(它会计算事务性 md5 的 and/or HTTPS 校验和,对于每个块)。
或者痛苦的选择:re-download 验证它的 MD5 是否有效。如果你想这样做,一个“简单”的方法是先设置 azure CONTENT-MD5 属性(见上文),然后使用 azure 客户端执行文件下载。在 client-side 上,它将在下载时计算 md5,将其与 azure 中的“当前设置”进行比较(如果存在于 azure 中,则作为下载 header 发送),客户端将失败如果最后不匹配则执行操作。所以基本上 azure 支持验证 client-side 上大文件的 full-file MD5,但不支持 server-side...或者创建一个 Azure function 来做一个等同于 client-side上传后验证。
Azure 还支持另外一种 MD5 类型的东西:如果你执行一个指定范围为 4MB 或更小的“get blob”,你也可以指定 x-ms-range-get-content-md5
并且它将 return you 那个跑的MD5e 在 CONTENT-MD5 HTTP header 中。 FWIW.