8
votes

I am trying to upgrade my project from Microsoft.WindowsAzure.Storage v9 (deprecated) to latest sdk Azure.Storage.Blobs v12.

My issue (post-upgrade) is accessing the ContentHash property.

Pre-upgrade steps:

  1. upload file to blob
  2. get MD5 hash of uploaded file provided by CloudBlob.Properties.ContentMD5 from Microsoft.WindowsAzure.Storage.Blob
  3. compare the calculated MD5 hash with the one retrieved from azure

Post-upgrade attempts to access the MD5 hash that Azure is calculating on its side:

1.BlobClient.GetProperties() calling this method

2.BlobClient.UploadAsync() looking at the BlobContentInfo response

both return ContentHash is null. (see my later Question to see why)

One huge difference I've noticed is that with older sdk I could tell to the storage client to use MD5 computing like this:

CloudBlobClient cloudBlobClient = _cloudStorageAccount.CreateCloudBlobClient();

cloudBlobClient.DefaultRequestOptions.StoreBlobContentMD5 = true;

So I was expecting to find something similar to StoreBlobContentMD5 on the latest sdk but I couldn't.

Can anyone help me find a solution for this problem?

Edit 1: I did a test and in azure storage I do not have a MD5 hash

Upload code:

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

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

StorageTransferOptions storageTransferOption = new StorageTransferOptions()
     {
          MaximumConcurrency = 2,
     };

var blobResponse = await blob.UploadAsync(stream, blobHttpHeaders, null, null, null, null, storageTransferOption, default);

return blob.GetProperties();

There is not much difference between old upload code and new one apart from using new classes from new sdk.

The main difference remains the one I already stated, I can not find an equivalent setting in new sdk for StoreBlobContentMD5 . I think this is the problem. I need to set the storage client to compute MD5 hash, as I did with old sdk.

Edit 2: For download I can do something like this:

var properties = blob.GetProperties();
var download = await blob.DownloadAsync(range: new HttpRange(0, properties.Value.ContentLength), rangeGetContentHash: true);

By using this definition of DownloadAsync I can force MD5 hash to be calculated and it can be found in download.Value.ContentHash

2
Can you confirm in the Azure Portal if the blob has a ContentHash? So that we know if the issue is with the upload or with the retrieval of attributes? Maybe you could post an example of your Upload and Download code too once we know where the issue is?Connor Dickson
I just did a test and in azure storage I do not have a MD5 hash.Cristian
Added a pic and a code snippet. blobResponse.ContentHash and blob.GetProperties().ContentHash are both null.Cristian
@Cristian As fra as I knew, if blob service api version is 2012-02-12 and later, the server will return MD hash in response header even when the request header does not include the Content-MD5: docs.microsoft.com/en-us/rest/api/storageservices/…Jim Xu
Yes, I read that too and based on that doc I was expecting to work....Surely I do something wrong, but I can't find what.Cristian

2 Answers

1
votes

Summarize to close the question:

I did a quick test with the latest version of 12.4.4 blob storage package, I can see the content-md5 is auto-generated and can also be read.

And as per the op's comment, it may due to some issues with the existing solution. And after creating a new solution, it works as expected.

1
votes

The short version of this problem is, make sure the Stream you upload to Azure using the v12 version of the SDK supports Seek (see the HasSeek property). It's currently required in order to traverse the Stream to generate the hash, and reset/seek the position back to 0 so that it can be read again for the actual upload.