top of page

Azure Blob Storage with .Net 5

Azure Blob Storage

Azure Blob storage is Microsoft’s object storage solution for the cloud. Blob storage is optimized for storing massive amounts of unstructured data. Unstructured data is data that doesn’t adhere to a particular data model or definition, such as text or binary data. It can be used in many ways and provides several types of resources. you more information on Azure Website or read Microsoft’s Introduction.


Create Azure Blob Storage

To use any azure service we have to signup for the Azure portal. users can use most of the service with free subscriptions. The free subscription is very handy for developers to learn about the azure service.


On the Azure portal dashboard page click on ‘Create a resource’.



Search for ‘Storage Account’ and click “Create”.



You need to fill some information…



  • ‘Resource group’ — enter the name of the resource group or create new. Resource groups are just separators or wrappers.

  • ‘Storage account name’ — enter the unique name and this name will be used for creating the base address.

  • ‘Region — you can select the default or choose your nearest location value.

  • ‘Performance’ — chose your preferred option(for free subscription go for the ‘Standard’ option)

  • ‘Redundancy -ensures that your storage account meets its availability and durability targets even in the face of failures.

Once you fill the information click “Review+Create”

Then click “Create”



After a few times, storage will be deployed and you can click “Go to resource”



Here in “Access Keys” you can copy connection string, we will use that to connect blob storage.



Install Packages

To communicate with azure blob storage you need to install “Azure.Storage.Blobs” package.

Package Manager:
Install-Package Azure.Storage.Blobs -Version 12.10.0

CLI:

dotnet add package Azure.Storage.Blobs --version 12.10.0


appsettings.json

"ConnectionStrings": {
  "AzureBlobStorage": ""
}

paste your connection string in appsettings.json file.


startup.cs

add BlobServiceClient in DI Container.

services.AddScoped(x => new BlobServiceClient(configuration.GetConnectionString("AzureBlobStorage")));


Interfaces

Service for blob operations…

public interface IBlobService
{
    IAsyncEnumerable<string> GetListAsync(string container,CancellationToken cancellationToken);
    
    Task<string?> GetAsync(GetBlobRequest request);
    
    IAsyncEnumerable<string?> GetAllAsync(string container,CancellationToken cancellationToken);
    
    Task<string> SaveAsync(SaveBlobRequest request, CancellationToken cancellationToken);

    Task<bool> DeleteAsync(DeleteBlobRequest request,CancellationToken cancellationToken);
}

and service for containers.

public interface IContainerService
{
    IAsyncEnumerable<string> GetAsync();   
    Task<bool> DeleteAsync(string container);
}


Implementation


BlobService

public class BlobService : IBlobService
{
    private readonly BlobServiceClient _blobServiceClient;
    private readonly ILogger<BlobService> _logger;

    public BlobService(BlobServiceClient blobServiceClient, ILogger<BlobService> logger) =>
        (_blobServiceClient, _logger) = (blobServiceClient, logger);

    public async IAsyncEnumerable<string> GetListAsync(string container,
        [EnumeratorCancellation] CancellationToken cancellationToken)
    {
        var blobContainer = _blobServiceClient.GetBlobContainerClient(container);
        await foreach (var blob in blobContainer.GetBlobsAsync(cancellationToken:cancellationToken))
            yield return blob.Name;
    }

    public async Task<string?> GetAsync(GetBlobRequest request)
    {
        var blobContainer = _blobServiceClient.GetBlobContainerClient(request.Container);
        var blobClient = blobContainer.GetBlobClient(request.Blob);
        return blobClient.Uri.AbsoluteUri;
    }

    public async IAsyncEnumerable<string?> GetAllAsync(string container,
        [EnumeratorCancellation] CancellationToken cancellationToken)
    {
        await foreach (var blob in GetListAsync(container,cancellationToken))
            yield return await GetAsync(new GetBlobRequest(blob, container));
    }

    public async Task<string> SaveAsync(SaveBlobRequest request, CancellationToken cancellationToken)
    {
        var extension = Path.GetExtension(request.Blob.FileName);
        var blobContainer = _blobServiceClient.GetBlobContainerClient(request.Container);
        await blobContainer.CreateIfNotExistsAsync(PublicAccessType.BlobContainer, null,cancellationToken);
        var blobName = request.HasDefaultName
            ? request.Blob.FileName
            : $"{Guid.NewGuid():N}{extension}";
        var blobClient = blobContainer.GetBlobClient(blobName);
        if (await blobClient.ExistsAsync(cancellationToken))
        {
            _logger.LogInformation("Blob with name {blobName} already exists.", blobName);
            return string.Empty;
        }
        await blobClient.UploadAsync(request.Blob.OpenReadStream(), cancellationToken);
        return blobClient.Uri.AbsoluteUri;
    }

    public async Task<bool> DeleteAsync(DeleteBlobRequest request,CancellationToken cancellationToken)
    {
        var blobContainer = _blobServiceClient.GetBlobContainerClient(request.Container);
        return (await blobContainer.DeleteBlobIfExistsAsync(request.Blob,cancellationToken:cancellationToken)).Value;
    }
}

Request types:

public class SaveBlobRequest
{
    public SaveBlobRequest() { }

    public SaveBlobRequest(IFormFile blob, bool hasDefaultName, string container) =>
        (Blob, HasDefaultName, Container) = (blob, hasDefaultName, container);

    public IFormFile Blob { get; set; }
    
    public bool HasDefaultName { get; set; }
    
    public string Container { get; set; }
}public class DeleteBlobRequest
{
    public string Blob { get; set; }
    
    public string Container { get; set; }
}


ContainerService

public class ContainerService : IContainerService
{
    private readonly BlobServiceClient _blobServiceClient;

    public ContainerService(BlobServiceClient blobServiceClient)
    {
        _blobServiceClient = blobServiceClient;
    }
    
    public async IAsyncEnumerable<string> GetAsync()
    {
        await foreach (var container in _blobServiceClient.GetBlobContainersAsync()) 
            yield return container.Name;
    }

    public async Task<bool> DeleteAsync(string container)
    {
        var blobContainer = _blobServiceClient.GetBlobContainerClient(container);
        return (await blobContainer.DeleteIfExistsAsync()).Value;
    }
}


Dependency Injection

Then you need to inject services into DI Container and use in api endpoints or controller methods.

services.AddScoped<IBlobService, BlobService>();
services.AddScoped<IContainerService, ContainerService>();


Endpoints

Blob endpoints

[HttpGet]
public override async Task<ActionResult<string?>> HandleAsync([FromQuery]GetBlobRequest getBlobRequest,
    CancellationToken cancellationToken = new())
{
    var response = await _blobService.GetAsync(getBlobRequest);
    return Ok(response);
}

[HttpPost]
public override async Task<ActionResult<string>> HandleAsync([FromForm]SaveBlobRequest saveBlobRequest,
    CancellationToken cancellationToken = new())
{
    return Ok(await _blobService.SaveAsync(saveBlobRequest, cancellationToken));
}


container endpoints

[HttpGet]
public override async Task<ActionResult<IAsyncEnumerable<string>>> HandleAsync(
    CancellationToken cancellationToken = new())
{
    return Ok(_container.GetAsync());
}[HttpDelete]
public override async Task<ActionResult<bool>> HandleAsync([FromQuery]string container,
    CancellationToken cancellationToken = new())
{
    return Ok(await _container.DeleteAsync(container));
}



Source: Medium - Levan Revazashvili


The Tech Platform

0 comments
bottom of page