Uploading blockblob and setting contenttype
Asked Answered
T

6

44

I'm using Microsoft.WindowsAzure.Storage.* library from C#.

This is how I'm uploading things to storage:

// Store in storage
CloudStorageAccount storageAccount = CloudStorageAccount.Parse("...connection string...");
CloudBlobClient blobClient = storageAccount.CreateCloudBlobClient();
CloudBlobContainer container = blobClient.GetContainerReference("pictures");

// Create container if it doesnt exist
container.CreateIfNotExists();

// Make available to everyone
container.SetPermissions(new BlobContainerPermissions
{
    PublicAccess = BlobContainerPublicAccessType.Blob
});

// Save image
CloudBlockBlob blockBlob = container.GetBlockBlobReference("blah.jpg");
blockBlob.UploadFromByteArray(byteArrayThumbnail, 0, byteArrayThumbnail.Length);
blockBlob.Properties.ContentType = "image/jpg";  // *** NOT WORKING ***

All the things I upload to the storage are being saved with content type "application/octet-stream", even though I'm using the setter with value "image/jpg" (see the last line in my code).

So question #1: Why isn't working the ContentType setter?

And question #2: If I manually change the content type to "image/jpg", using Windows Azure management portal, and then copy the absolute URI of the file to the browser's address field, and press enter, the jpg file is downloaded instead of displayed. Isn't this mime type supposed to be displayed instead of downloaded? How do I change this?

Terri answered 7/7, 2014 at 23:47 Comment(0)
G
116

Actually you don't have to call SetProperties method. In order to set content type while uploading the blob, just set the ContentType property before calling the upload method. So your code should be:

// Save image
CloudBlockBlob blockBlob = container.GetBlockBlobReference("blah.jpg");
blockBlob.Properties.ContentType = "image/jpg";
blockBlob.UploadFromByteArray(byteArrayThumbnail, 0, byteArrayThumbnail.Length);

and that should do the trick.

Gilbart answered 8/7, 2014 at 2:57 Comment(8)
Whoa!, I'd accept both answers :/ anyway, no one answered my second question: when I put the URL in the browser, it downloads the image as a file instead of being displayed. Tried image/jpeg and image/jpg.Terri
Actually I tried uploading a JPG file and set its content type to be image/jpg. When I put the URL in the browser, I was able to see the image in the browser. I tried with IE/Firefox/Chrome. Can you please trace the request/response in Fiddler and see the actual content type returned by storage service?Gilbart
You uploaded via SDK or directly from the Azure Portal? I will try the traceTerri
Actually that's not true, I believe you may be seeing this behavior because of the file name having an extension on it. If you use some other identifier for the name of the blob (like a database key) or use a name that does not have an extension, you will not get this behavior.Workroom
Here is a blog post with a comprehensive list of extension to mimetype mappings. ppolyzos.com/2015/10/27/…Hygrothermograph
This does not set the content-type. It might have worked for you because of the jpg extension in the blob name.Metacenter
what is actually the benefit of setting the contenttype?Staysail
So that blob can be interpreted properly. For example, an image file is displayed inline in the browser instead of being downloaded.Gilbart
J
23

Unfortunately, none of the answers provided here is currently working for the latest SDK (12.x.+)

With the latest SDK, the content type should be set via BlobHttpHeaders.

var _blobServiceClient = new BlobServiceClient("YOURCONNECTIONSTRING");

var containerClient = _blobServiceClient.GetBlobContainerClient("YOURCONTAINERNAME");

var blob = containerClient.GetBlobClient("YOURFILE.png");

var blobHttpHeader = new BlobHttpHeaders();

blobHttpHeader.ContentType = "image/png";

var uploadedBlob = await blob.UploadAsync(YOURSTREAM, blobHttpHeader);
Jenna answered 9/6, 2020 at 21:14 Comment(2)
The perfect solution for people who are working with latest Azure Blob SDKs (v12 and above). Thanks!Hennessy
How can you combine this with overwrite any existing file? edit: actually looks like you don't need it when you add these options.Aerification
C
22

After you make any changes to Properties, you have to make a call to CloudBlockBlob.SetProperties() to actually save those changes.

Think of it as something similar to LINQ-to-Entities. You can make any changes you want to your local object, but until you call SaveChanges(), nothing is actually saved.

Civic answered 8/7, 2014 at 0:52 Comment(2)
The SetProperties method should be used for UPDATING blobs not while CREATING.Salpiglossis
SetProperties should be used for any time, regardless if it's the first time create or update. From my observation, if you use a filename (with extension) then it defaults the ContentType to something that matches the extension. If you want to ensure it always sets it to the content type you expect, I'd (1) uploading the data, (2) set your content tye (3) call SetProperties() azure.microsoft.com/en-us/documentation/articles/…Workroom
C
22

Using the new SDK Azure.Storage.Blobs

BlobHttpHeaders blobHttpHeaders = new BlobHttpHeaders();
blobHttpHeaders.ContentType = "image/jpg";
blobClient.SetHttpHeaders(blobHttpHeaders);
Capping answered 21/5, 2020 at 19:48 Comment(1)
It crashes with BlockBlobClient.UploadAsync(Stream, BlobUploadOptions, CancellationToken) if the blob contains one piece only: Status: 404 (The specified blob does not exist.) The correct way is to set BlobUploadOptions.Headers before calling UploadAsync.Corded
F
3

Obviously best to set it on create like Gaurav Mantri's answer, if you are past that point and need to update the other answers here may mess you up.

// GET blob
CloudBlobContainer container = blobClient.GetContainerReference(containerName);
CloudBlockBlob blockBlob = container.GetBlockBlobReference(fileName); 

// if you don't do this you'll wipe properties you didn't mean to
await blockBlob.FetchAttributesAsync();

// SET
blockBlob.Properties.ContentType = mimetype;

// SAVE
await blockBlob.SetPropertiesAsync();
Fruition answered 3/4, 2020 at 22:55 Comment(0)
C
1

with the new version of the Azure Blob SDK this is no longer working.

this worked for me:

CloudBlockBlob blockBlob = cloudBlobContainer.GetBlockBlobReference(blobName);
blockBlob.Properties.ContentType = contentType;                            
await blockBlob.SetPropertiesAsync();
Colporteur answered 23/4, 2018 at 12:2 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.