ContentHash 未在 Azure Blob Storage v12 中计算

ContentHash not calculated in Azure Blob Storage v12

继续传奇,这是第一部分:

经过大量调试,根本原因似乎是 上传 blob 后未计算内容哈希值,因此 BlobContentInfoBlobProperties 返回一个空内容哈希,我的整个流程基于从 Azure 接收哈希。

我发现这取决于我调用并上传到 azure 的 HttpRequest 流方法:

HttpRequest.GetBufferlessInputStream(),没有计算content hash,即使我进入azure storage explorer,blob的ContentMD5也是空的

HttpRequest.InputStream()一切正常。


你知道为什么会有这种不同的行为吗?你知道如何接收通过 GetBufferlessInputStream 方法接收的流的内容哈希吗?

因此代码流如下所示:

var stream = HttpContext.Current.Request.GetBufferlessInputStream(disableMaxRequestLength: true)

var container = _blobServiceClient.GetBlobContainerClient(containerName);
var blob = container.GetBlockBlobClient(blobPath);

BlobHttpHeaders blobHttpHeaders = null;
if (!string.IsNullOrWhiteSpace(fileContentType))
{
     blobHttpHeaders = new BlobHttpHeaders()
     {
          ContentType = fileContentType,
     };
}

// retry already configured of Azure Storage API
await blob.UploadAsync(stream, httpHeaders: blobHttpHeaders);

return await blob.GetPropertiesAsync();

在上面的代码片段中 ContentHash 没有被计算,但是如果我改变我从 http 请求中获取流的方式,下面的代码片段 ContentHash 被计算。

var stream = HttpContext.Current.Request.InputStream

P.S。我认为这很明显,但是对于旧的 sdk,内容哈希是为 GetBufferlessInputStream 方法

接收的流计算的

P.S2 您还可以在 github 上找到未解决的问题:https://github.com/Azure/azure-sdk-for-net/issues/14037

P.S3 添加代码片段

解决方法是当通过GetBufferlessInputStream()方法获取流时,将其转换为MemoryStream,然后上传MemoryStream。然后它可以生成contenthash。示例代码如下:

        var stream111 = System.Web.HttpContext.Current.Request.GetBufferlessInputStream(disableMaxRequestLength: true);
        //convert to memoryStream.
        MemoryStream stream = new MemoryStream();
        stream111.CopyTo(stream);
        stream.Position = 0;

        //other code
        // retry already configured of Azure Storage API
        await blob.UploadAsync(stream, httpHeaders: blobHttpHeaders);

不知道为什么,但根据我的调试,我可以看到在最新的 SDK 中使用方法 GetBufferlessInputStream() 时,在上传过程中,它实际上调用了 Put Block api in the backend. And in this api, MD5 hash is not stored with the blob(Refer to here 以获取详细信息。)。截图如下:

但是,当使用 InputStream 时,它会调用 Put Blob api。截图如下:

运行今天进入这个。从我的挖掘来看,这似乎是您用来上传的 Stream 类型的症状,它并不是真正的错误。为了为您的 blob 生成哈希(这是在客户端上传之前通过它的外观完成的),它需要读取流。这意味着它需要在生成哈希后将流的位置重置回 0(对于实际的上传过程)。这样做需要能够对流执行 Seek 操作。如果您的流不支持 Seek,那么看起来它不会生成哈希。

要解决此问题,请确保您提供的流支持 Seek (CanSeek)。如果没有,则使用不同的 Stream/copy 您的数据到存在的流(例如 MemoryStream)。另一种方法是让 Blob SDK 的内部为您执行此操作。