Blazor Upload File to Azure Blob Storage

REAL-WORLD BLAZOR: UPLOAD FILES TO AZURE BLOB STORAGE

by

This tutorial will build off a previous tutorial where you learned how to implement drag-and-drop file uploads using Blazor. We will be learning how to use BlazorInputFile to upload a file to an Azure storage blob.

Getting Started

If you haven't already set up a blob storage container in your Azure portal, do that first. Then, be sure you have the BlazorInputFile Nuget package installed for your project.

Install-Package BlazorInputFile

In this tutorial, I am working with server-side Blazor application, so be sure to add the BlazorInputFile script to your _Host.cshtml file.

<script src="_content/BlazorInputFile/inputfile.js"></script>

Handling File Input

Once you have designed your drag-and-drop interface, you will want to do something with the uploaded file. For the sake of code readability, this tutorial assumes a single file input bound to a var named selectedImage, but you could extend this guide for use with an input that accepts multiple files.

private IFileListEntry selectedImage;
private string dataUri;

Configure the OnChange event handler of your InputFile element to set the value of selectedImage.

private async Task HandleImageInputChange(IFileListEntry[] files)
{
	var rawFile = files.FirstOrDefault();
	if (rawFile != null)
	{
		selectedImage = await rawFile.ToImageFileAsync(rawFile.Type, 512, 512);
		
		var stream = new MemoryStream();
		await selectedImage.Data.CopyToAsync(stream);

		dataUri = $"data:{rawFile.Type};base64,{Convert.ToBase64String(stream.ToArray())}";
	}
}

When a file is selected, the above code takes the raw file and converts it to an image file with maximum dimensions of 512px by 512px when. You should first add a check to make sure the uploaded file is of an accepted file type. If you need help, the previous drag-and-drop tutorial gives a demonstration for this and other error checks.

Because I think it makes for a good user experience, I also saved a dataUri string from the uploaded file. This could be used to immediately provide visual feedback of the uploaded file.

<img src="@dataUri">

File Upload Event Handlers

Next, in your form's submit handler, you should upload your file to the blob container in your Azure Storage account. Your handler may look something like the following.

private async Task SubmitForm()
{
	if (selectedImage != null)
	{
		//extract just base64 string without data:image/png;base64 (for example)
		var base64Data = Regex.Match(dataUri, @"data:image/(?<type>.+?),(?<data>.+)").Groups["data"].Value;
		var bytes = Convert.FromBase64String(base64Data);

		using (var stream = new MemoryStream(bytes))
		{
			var uploadedUri = await storageService.UploadFileToStorage(stream, "images", selectedImage.Name);

			//display a success message
		}
	}
}

You will notice a couple things that we have not defined yet. First, there is a storageService instance with an UploadFileToStorage() method. We will work on defining the contents of this class, shortly. But first, we need to talk about the storageConfig instance from IOptions. This contains the configuration information for your own Azure storage account. Let's create a strongly-typed definition for this class and add it to our application's Configuration collection.

Azure Storage Configuration

Since we want to make a strongly-typed configuration, create a Config folder for your project, and add a file called AzureStorageConfig.cs. You will use this to bind your Azure secrets and IOptions storage configuration in a way that can easily be injected into your Blazor components.

To upload a file, you will need your Azure Storage account name and an access key for your Azure Storage account. Get these from the Azure portal. Your AzureStorageConfig class might look like the following.

public class AzureStorageConfig
{
	public string AccountName { get; set; }
	public string AccountKey { get; set; }
}

Next, add the value for those items to your project's secret manager, such as secrets.json for a development environment.

{
	"AzureStorageConfig": {
		"AccountName": "",
		"AccountKey": ""
	}
}

Finally, add the configuration to the service collection in the ConfigureServices() method of Startup.cs.

services.AddOptions();
services.Configure<AzureStorageConfig>(Configuration.GetSection("AzureStorageConfig"));

Uploading Files to Azure

Now, let's explore the code you will actually need to save your file to your Azure Storage blob account. I am going to write the method as a transient service with configuration accessed through dependency injection, but you could also write it as a helper class with configuration passed in as a parameter. Create a Services folder in your Blazor project, and add a file called AzureStorageService.cs.

Include the namespace for the required Nuget packages.

using Azure.Storage;
using Azure.Storage.Blobs;

Use dependency injection to retrieve an instance of your AzureStorageConfig options and upload the file to Azure blob storage.

public class AzureStorageService
{
	private readonly IOptions<AzureStorageConfig> _options;
	public AzureStorageService(IOptions<AzureStorageConfig> options)
	{
		_options = options;
	}

	public async Task<Uri> UploadFileToStorage(Stream stream, string container, string fileName)
	{
		Uri blobUri = new Uri("https://" +
							  _options.Value.AccountName +
							  ".blob.core.windows.net/" +
							  container + "/" + fileName);

		StorageSharedKeyCredential storageCredentials =
			new StorageSharedKeyCredential(_options.Value.AccountName, _options.Value.AccountKey);

		// Create the blob client.
		BlobClient blobClient = new BlobClient(blobUri, storageCredentials);

		// Upload the file
		await blobClient.UploadAsync(stream, true);

		return blobUri;
	}
}

In this example, I am intentionally using the filename of the original file. Be aware, this will override the file in Azure Storage if you upload another file with the same name. If that is not what your use-case requires, be sure to make the necessary adjustments.

Add an instance of the service you just created to the service collection. In the ConfigureService() method of Startup.cs, add the following line.

services.AddTransient<AzureStorageService>();

Finally, inject an instance of this service into the appropriate Blazor component.

@inject AzureStorageService storageService

The Bottom Line

In this tutorial, you wrote a service that can be used to securely upload files to an Azure Storage blob container. It uses your Azure Storage accounts access key to upload a file to a designated container. This service can be injected into any Blazor page or component in your project that requires it, such as those offering file uploads using the BlazorInputFile project.


Don't stop learning!

There is so much to discover about C#. That's why I am making my favorite tips and tricks available for free. Enter your email address below to become a better .NET developer.


Did you know?

Our beautiful, multi-column C# reference guides contain more than 150 tips and examples to make it even easier to write better code.

Get your cheat sheets