如何解决从 Windows Azure Blob 存储服务返回的 InvalidMd5 错误?

2024-01-05

我正在构建一个应用程序,需要允许用户将大图像(最多约 100 MB)上传到 Windows Azure Blob 存储服务。读过罗布·吉伦的精彩文章 http://rob.gillenfamily.net/2010/04/26/external-file-upload-optimizations-for-windows-azure/关于Windows Azure的文件上传优化,我借用了他的方法来并行上传文件块,使用CloudBlockBlob.PutBlock() http://msdn.microsoft.com/en-us/library/ee772903.aspx内的方法并行.For http://msdn.microsoft.com/en-us/library/system.threading.tasks.parallel.for.aspx循环(代码可用here http://code.google.com/p/scientificcloudcomputing/source/browse/trunk/AzureTesting/AzureTesting/Program.cs).

我遇到的问题是,每当我尝试上传文件时,我都会收到“无效的MD5 http://msdn.microsoft.com/en-us/library/dd179357.aspx“例外情况存储客户端 http://msdn.microsoft.com/en-us/library/microsoft.windowsazure.storageclient.cloudblobclient.aspx。由于怀疑问题可能出在开发存储中,我还尝试针对我的实时 Azure 存储帐户运行代码,但遇到了相同的错误。查看交通情况Fiddler http://www.fiddler2.com/fiddler2/我看到“内容-MD5“标头设置为有效的 MD5 哈希值。错误的描述如下:”请求中指定的MD5值无效。 MD5 值必须是 128 位且采用 Base64 编码。”,但据我所知,我看到在 Fiddler 中发送的值是有效的(例如a91c588092cedbdb1b82c2d3786fd509).

这是我用来计算哈希值的代码(由 Rob Gillen 提供):

public static string GetMD5HashFromStream(byte[] data)
{
    MD5 md5 = new MD5CryptoServiceProvider();
    byte[] retVal = md5.ComputeHash(data);

    StringBuilder sb = new StringBuilder();
    for (int i = 0; i < retVal.Length; i++)
    {
        sb.Append(retVal[i].ToString("x2"));
    }
    return sb.ToString();
}

这是对 PutBlock() 的实际调用:

blob.PutBlock(transferDetails[j].BlockId, new MemoryStream(buff), blockHash, options);

我也尝试像这样传递哈希:

Convert.ToBase64String(Encoding.UTF8.GetBytes(blockHash))

但结果是一样的——”无效的MD5“ 错误 :(

MD5 哈希值通过 Base64 编码传递给 PutBlock()(例如YTkxYzU4ODA5MmNlZGJkYjFiODJjMmQzNzg2ZmQ1MDk=)和没有它(例如a91c588092cedbdb1b82c2d3786fd509)似乎没有什么区别。

Rob's code http://code.google.com/p/scientificcloudcomputing/source/browse/trunk/AzureTesting/AzureTesting/Program.cs显然为他工作,我真的不知道是什么导致了我的情况的问题。我对 Rob 的代码所做的唯一更改是更改 ParallelUpload() 扩展方法以采用 Stream 而不是文件名,并根据上传文件的大小动态确定块大小。

请,如果有人知道如何解决这个问题,请告诉我!我将非常感激!我已经为此损失了两天的时间。


Rob,感谢您提供帮助并指出 MD5 哈希值的差异。你的回答让我朝着正确的方向思考。我又花了一整天的时间来研究这个问题,但幸运的是(并且感谢你的评论:))我终于成功解决了这个问题。事实证明,我的案例实际上存在两个问题:

1) MD5 哈希值:我注意到您在答案中粘贴的哈希值比我得到的哈希值短,但我花了一段时间才看到您的答案是否正确twice更短。经过一些实验我发现从流中获取MD5Hash()您的测试应用程序中的方法正在转换16-byte生成的哈希值MD5加密服务提供者 to a 32 个字符细绳。正是这个 32 个字符的字符串导致了问题,因为它被转换为Base64并传递给PutBlock()方法,因此 Blob 存储服务抱怨的哈希值更长且无效。这是我最终得到的代码:

原来的:

public static string GetMD5HashFromStream(byte[] data)
{
    MD5 md5 = new MD5CryptoServiceProvider();
    byte[] retVal = md5.ComputeHash(data);

    StringBuilder sb = new StringBuilder();
    for (int i = 0; i < retVal.Length; i++)
    {
        sb.Append(retVal[i].ToString("x2"));
    }
    return sb.ToString();
}

以及对 PutBlock() 的调用:

// calculate the block-level hash
string blockHash = Helpers.GetMD5HashFromStream(buff);
blob.PutBlock(transferDetails[j].BlockId, new MemoryStream(buff), blockHash, options);

Final:

MD5 md5 = new MD5CryptoServiceProvider();
byte[] blockHash = md5.ComputeHash(buff);
string convertedHash = Convert.ToBase64String(blockHash, 0, 16);
blob.PutBlock(transferDetails[j].BlockId, new MemoryStream(buff), convertedHash, options);

Rob,我真的很好奇你的代码在你的情况下是如何工作的,为什么在我的情况下却不起作用——这是否是我机器上的设置所特有的,或者可能是不同版本的 Azure 工具(我使用的是 v1.1)。 2)...如果您有任何想法,请告诉我。

2) 开发存储中的一个错误: 大量的网络梳理让我发现这一页 http://msdn.microsoft.com/en-us/library/dd320275.aspx其中提到了开发存储中一个不起眼但显然已知的错误:

如果两个请求尝试上传 阻止尚未执行的 blob 存在于开发存储中,一 请求将创建 blob,并且 其他可能返回状态代码 409 (冲突),与存储服务 错误代码 BlobAlreadyExists。

以下是我想出的解决方法:

public static bool IsDevelopmentStorageRunning()
{
    return new Microsoft.ServiceHosting.Tools.DevelopmentStorage.DevStore().IsRunning();
}

您需要添加对Microsoft.ServiceHosting.Tools.dll,它位于“C:\Program Files\Windows Azure SDK\v1.2\bin“在我的机器上。然后,我在并行.For处理文件块的循环如下:

bool isDevStorageRunning = StorageProxy.IsDevelopmentStorageRunning();
ParallelOptions parallelOptions = new ParallelOptions();
parallelOptions.MaxDegreeOfParallelism = isDevStorageRunning ? 1 : 4;
Parallel.For(0, transferDetails.Length, parallelOptions, j => { ... });

我希望这能帮别人省去我所经历的所有麻烦。罗布,再次感谢您的帮助:)

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

如何解决从 Windows Azure Blob 存储服务返回的 InvalidMd5 错误? 的相关文章

随机推荐