Sometimes, you will need to reference a file on a web page, if that file is stored as a blob in an Azure Storage Account than you may want to also force the download of that file or force the displaying of the file in the browser. This is done using the Content Disposition header but that alone will not make this just work, check out this post to learn more about the process.

The solution to getting this work is pretty simple. To give a bit of background first though, I’m sure you are all aware of the situation, you click a file download link in the browser and it either opens up in the browser or downloads the file. That depends on if the browser and operating system know about that file type for one and second how the HTTP header Content-Disposition is set and handled through the response.

You can set this response header using .NET Core to force the browser to behave in a specific way. Once more if you’re file is stored in blob storage in Azure then it’s easy to retrieve that file and pass it through to the browser.

First of all, to get your code ready, you will need the Microsoft.Azure.Storage and Microsoft.Azure.Storage.Blob packages from NuGet, simple run the following commands in your package manager to retrieve it.

Install-Package Microsoft.Azure.Storage
Install-Package Microsoft.Azure.Storage.Blob

As this is .NET Core the function below is designed to be added to a controller, you will notice it is an async method that returns a FileStreamResult, we pass in two parameters which are container and file, this is to just retrieve the file from blob storage.

Let’s look at the code in more detail.

var storageAccount = CloudStorageAccount.Parse("");
var blobClient = storageAccount.CreateCloudBlobClient();

Firstly, we need to connect to the storage account, you do this with your connection string, which I would highly recommend retrieving from a Key Vault in a production environment.   Next we need to create a new Uri object to where our object is located, this is where we pass in the parameters to our method.

var uri = new Uri($"https://<bloburl>/{container}/{file}");
var Blob = await blobClient.GetBlobReferenceFromServerAsync(uri);

Now it’s time to set the response code for the request if everything is ok and create a new Stream to the blob.

HttpResponseMessage message = new HttpResponseMessage(HttpStatusCode.OK);
Stream blobStream = await Blob.OpenReadAsync();

Next I am setting a string which sets the filename for the file, we will use this when setting the Content-Disposition header later.

var fileName = string.Format("{0}{1}", DateTime.Now.Date.ToString("ddMMMy").ToUpper(), Path.GetExtension(uri.AbsoluteUri));

Finally, we set the response header and then return the object along with the appropriate content type from the blob, making the method work for any file type.

Response.Headers.Append("Content-Disposition", "inline; filename=" + fileName);
return File(blobStream, Blob.Properties.ContentType);

The magic here happens because of the values we set in the Content-Disposition header. By setting the value to inline and then passing a filename, we force the download to be handled by the browser if it can handle that content type and the file name will be a temporary one we set in the code. If you set the initial part of Content-Disposition to attachment rather than inline then it will instead force a download rather than render in the browser.

The full method is available up on my GitHub repository for the blog.

Summary

There you have it, a nice, quick and easy way to download files from blob storage through a .NET Core application. You can of course quite easily change this to work with other platforms based on C#.