Upload files to Azure Blob Storage using Asp.Net Core Web API

Upload files to Azure Blob Storage using Asp.Net Core Web API

Introduction

In this article, we are going to see how we can upload multiple files in Azure Blob Storage using Core REST APIs. I'll be using the Free Tier of the Azure account which provides sufficient resources to play around.

Setting up Azure Blob Storage

Let us first quickly spin up a basic Azure Blob Storage resource on the Azure portal where we will be uploading our files.

  1. Creating an Azure storage account

    • Go to the Azure portal (portal.azure.com) and log in with your account.

    • Click on the "Create a resource" button and search for "Storage account".

    • Click on the "Storage account" option and then click the "Create" button.

    • Fill out the required information, including the subscription, resource group, and storage account name.

    • For the free trial leave the pre-selected values for Region, Performance and Redundancy unchanged.

    • Other fields can be skipped as they are not required for this demo.

    • Finally, click on "Review + create" and then "Create".

  2. Setting up a container for storing the files

    • Once the storage account has been created, go to the storage account page in the Azure portal.

    • In the left navigation menu, click on "Containers".

    • Click on the "New container" button to create a new container (named here as "apiimages") for storing the files.

    • Give the container a name, select a public access level, and then click on "Create".

  3. Generating the connection string for accessing the storage account from the C# code

    • Go back to the storage account page in the Azure portal.

    • Click on "Access keys" in the left navigation menu.

    • Copy the connection string for key 1 and save it for later use in the REST API.

Setting up Dot Net Core Web API Project

I'll be using the latest version of the Web API based project in Visual Studio here and the only Nuget dependency required is Azure.Storage.Blobs.

Controller

The requirement is to have two endpoints one to upload multiple files and the other to fetch the details of those files from Azure.

C# provides us with a type called IFormFile which can be used to send a file over an HTTP Request. We will be using a collection of this type to support the option of multiple file uploads.

using AzureBlob.API.Service;
using Microsoft.AspNetCore.Mvc;

namespace AzureBlob.API.Controllers
{
    [Route("api/[controller]")]
    [ApiController]
    public class AttachmentController : ControllerBase
    {
        AzureBlobService _service;
        public AttachmentController(AzureBlobService service)
        {
            _service = service;
        }

        [HttpPost]
        public async Task<IActionResult> UploadBlobs(List<IFormFile> files)
        {
            var response = await _service.UploadFiles(files);
            return Ok(response);
        }

        [HttpGet]
        public async Task<IActionResult> GetAllBlobs()
        {
            var response = await _service.GetUploadedBlobs();
            return Ok(response);
        }

    }
}

There is no business logic implemented in the controller and we just pass on the request to the AzureBlobService which we are going to implement next.

Blob Service to access Azure

There are multiple ways to connect to Azure Storage account from C# and we are going to make use of the connection string which we copied and saved earlier.

I'll add a link for reference below which describes the other mechanism through which this connection can also be established like Azure AD, SAS Token etc.

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

namespace AzureBlob.API.Service
{
    public class AzureBlobService
    {
        BlobServiceClient _blobClient;
        BlobContainerClient _containerClient;
        string azureConnectionString = "<Primary Connection String>";
        public AzureBlobService()
        {
            _blobClient = new BlobServiceClient(azureConnectionString);
            _containerClient = _blobClient.GetBlobContainerClient("apiimages");
        }

        public async Task<List<Azure.Response<BlobContentInfo>>> UploadFiles(List<IFormFile> files)
        {

            var azureResponse = new List<Azure.Response<BlobContentInfo>>();
            foreach(var file in files)
            {
                string fileName = file.FileName;
                using (var memoryStream = new MemoryStream())
                {
                    file.CopyTo(memoryStream);
                    memoryStream.Position = 0;
                    var client = await _containerClient.UploadBlobAsync(fileName, memoryStream, default);
                    azureResponse.Add(client);
                }
            };

            return azureResponse;
        }

        public async Task<List<BlobItem>> GetUploadedBlobs()
        {
            var items = new List<BlobItem>();
            var uploadedFiles = _containerClient.GetBlobsAsync();
            await foreach (BlobItem file in uploadedFiles)
            {
                items.Add(file);
            }

            return items;
        }
    }
}

First, make use of the BlobServiceClient class exposed by the Azure.Storage.Blob namespace to create a client with the connection string.

We then need to fetch the particular container on which we intend to perform the operations. This is done using the GetBlobContainerClient with the container name as a parameter on the BlobServiceClient object.

The container client has a method to directly upload blobs to Azure using a file stream and the name of the file. In the UploadFiles function we make use of this feature and convert the IFormFile to a FileStream type and pass it on to the UploadBlobAsync

The response from Azure is of type BlobContentInfo which contains multiple properties describing the file just uploaded.

The container client also introduces a method called GetBlobsAsync which returns an async pageable BlobItem type which can be iterated upon to get the individual item. This method returns all the blobs available in the container and has parameters to allow pagination and other filtering capabilities.

Also, make sure to inject the dependency of the AzureBlobService in the startup or Program file based on the DotNet Core version so that it is available in the constructor of our AttachmentController defined above.

builder.Services.AddSingleton<AzureBlobService>();

That's it, we have the code in place to accept files and then pass them on to Azure. Let's test our code out using Postman

Testing using Postman

Postman provides us with the capability to upload multiple in the body of our HTTP request. This can be done using the form-data type of content and selecting the File type as File from the drop-down.

The key name here is the same as the variable name in the Post method of our API. For the value part, multi-select is allowed and the same can be utilized to select the files to be uploaded.

The response from the API if all goes through should be something like the below and the selected files should also be available in the container on azure.

Conclusion

We have successfully uploaded and fetched files from Azure Blob Storage using the Web APIs created in Asp.Net Core.

The source code for the demo application described here is available on GitHub.

Some of the links for reference are mentioned below

Thanks for reaching this far and I hope this article helped you in some way for the query which landed you here. Keep building.

Did you find this article valuable?

Support Rajat Srivastava by becoming a sponsor. Any amount is appreciated!