Seamless Azure Blob Files Reading and Writing Using .NET

Last Update: August 27, 2024
Featured image of Mastering .NET for Seamless Azure Blob Files Reading and Writing Operations
Table of Contents
Contributors
Picture of Vivasoft Team
Vivasoft Team
Tech Stack
0 +
Want to accelerate your software development company?

It has become a prerequisite for companies to develop custom software products to stay competitive.

Azure Blob Storage offers a powerful solution for managing unstructured data in the cloud. With its flexibility and scalability, developers can efficiently store and manipulate files of any type. In this blog post, we’ll delve into “Azure Blob Files Reading and Writing,” focusing on essential operations such as creating, copying, moving, and deleting files using .NET.

By the end of this guide, you’ll be equipped to seamlessly integrate these file operations into your applications, maximizing the capabilities of cloud storage. Let’s get started!

Here is a snapshot of our goal:

Azure blob read write operations

Objective

This blog aims to provide a concise and practical guide for developers to master Azure Blob file operations using .NET. By the end of this tutorial, you will be able to:

  1. Understand the fundamental concepts of Azure Blob Storage and its importance in cloud computing

  2. Learn how to perform essential file operations, including creating, copying, moving, and deleting files, using .NET with Azure Blob Storage

  3. Gain hands-on experience through code examples and step-by-step instructions

  4. Feel confident in integrating Azure Blob Storage operations into their own .NET applications, thereby enhancing scalability and efficiency

  5. Have a solid foundation to explore advanced features and tailor Blob Storage solutions to meet specific application requirements

Prerequisites to Azure Blob Files Reading and Writing

Before diving into reading and writing files with Azure Blob Storage using .NET, it’s essential to lay the groundwork with some key prerequisites.

Understanding these foundational elements will not only streamline your development process but also help you avoid common pitfalls as you implement Azure’s powerful storage solutions.

In this section, Vivasoft’s .NET developer team has suggested the prerequisites that will cover the necessary tools, libraries, and configurations you need to have in place to ensure a smooth and efficient experience with Azure Blob Storage.

Let’s get started on setting up your environment for success!

  1. Azure Account: You need an active Microsoft Azure account to access Azure Blob Storage. If you don’t have one, you can sign up for a Azure free account.

  2. Azure Storage Account: Create an Azure Storage account to utilize Azure Blob Storage. Follow these steps to create one:

    i) Sign in to the Azure portal

    ii) In the left navigation pane, select “Create a resource”

    iii) Search for “Storage account” and select “Storage account – blob, file, table, queue”

    iv) Fill in the required details such as Subscription, Resource group, Storage account name, Location, etc.

    v) Review and create the storage account

  3. Access Key: Obtain the access key for your Azure Storage account, which is required to authenticate your applications. You can find the access key under the “Access keys” section in your Azure Storage account’s settings.

  4. Visual Studio or Visual Studio Code: Install Visual Studio or Visual Studio Code on your development machine. You can download Visual Studio from the official website or Visual Studio Code from here.

  5. .NET SDK: Install the latest version of .NET SDK on your machine. You can download it from the .NET downloads page.

  6. Azure.Storage.Blobs Package: Install the Azure.Storage.Blobs package via NuGet Package Manager in your .NET project. You can install it using the following command in the Package Manager:
  • Install-Package Azure.Storage.Blobs

With these prerequisites in place, you’re ready to start working with Azure Blob Storage using .NET. Let’s dive into the step-by-step guide!

Create a Web API: Here step-by-step instructions for creating a .NET API to interact with Azure Blob Storage:

Step 1: Create a projects

Create a project for Mastering .NET for Azure blob files reading and writing

Step 2: Choose a framework

Select the version of this project

Step 3: Finally your solution is ready!

Solution files of fileoperation project

Step 4: Configuration of Azure Storage Account in AppSettings.json and create a class to easily handle the “AzureStorageConfig” section variable.

				
					  "AzureStorageConfig": {
    "AccountName": "myaccount_name",
    "AccountKey": "myaccount_key",
    "ContainerName": "my_container",
    "ConnectionString": "my_connection_string"
  }
				
			
				
					namespace FileOperation.Domain;
 
public class AzureStorageConfig
{
    public string AccountName { get; set; }
    public string AccountKey { get; set; }
    public string ConnectionString { get; set; }
    public string ContainerName { get; set; }
}
				
			

Let’s register the AzureStorageConfig class in your Program.cs file

				
					var configStorage = builder.Configuration
                .GetSection("AzureStorageConfig")
                .Get<AzureStorageConfig>();
 
builder.Services.AddSingleton(configStorage);
				
			

Step 5: Install Azure Storage Blobs SDK

				
					<ItemGroup>
    <PackageReference Include="Azure.Storage.Blobs" Version="12.19.1" />
    <PackageReference Include="Microsoft.VisualStudio.Azure.Containers.Tools.Targets" Version="1.19.6" />
    <PackageReference Include="Swashbuckle.AspNetCore" Version="6.4.0" />
</ItemGroup>
				
			

Step 6: Now let’s create a shared service class for performing file operations on Azure Blob Storage, such as creating a Blob Service Client, creating a Blob Client and constructing a Blob SAS builder.

This service like that as Name “FileOperationHelperService” and dependency inject the “AzureStorageConfig” Class.

				
					public class FileOperationHelperService : IFileOperationHelperService
{
    private readonly AzureStorageConfig _config;
 
    public FileOperationHelperService(AzureStorageConfig config)
    {
        _config = config;
    }
}
				
			

Now create some necessary method in your “FileOperationHelperService” class. And define the “IFileOperationHelperService” the interface.

				
					public interface IFileOperationHelperService
{
    BlobServiceClient CreateBlobServiceClient();
 
    BlockBlobClient CreateBlobClient(string container, string blobName);

    BlobSasBuilder GetBlobSusBuilder(string containerName);
}
				
			

And the interface should be implement. And here The CreateBlobServiceClient method creates a BlobServiceClient instance using the provided connection string.

				
					public BlobServiceClient CreateBlobServiceClient()
{
    BlobServiceClient blobServiceClient = new BlobServiceClient(_config.ConnectionString);
 
    return blobServiceClient;
}

				
			

The CreateBlobClient method creates a BlockBlobClient for a specific blob within a container by first obtaining the container’s client using the BlobServiceClient and then getting the blob’s client from the container.

				
					public BlockBlobClient CreateBlobClient(string container, string blobName)
{
    var blobServiceClient = CreateBlobServiceClient();
 
    var containerClient = blobServiceClient.GetBlobContainerClient(container);
 
    return containerClient.GetBlockBlobClient(blobName);
}
				
			

The GetBlobSusBuilder method constructs a BlobSasBuilder object with the container name and specifies that the resource type is a container (“c”).

				
					public BlobSasBuilder GetBlobSusBuilder(string containerName) => new BlobSasBuilder()
{
    BlobContainerName = containerName,
    Resource = "c"
};
				
			

So our shared service class is ready let’s register the shared service class in Program.cs

				
					builder.Services.AddScoped<IFileOperationHelperService, FileOperationHelperService>();
				
			

Step 7: Now our configuration and share service is ok. Let’s create a service class that essential because it serves as the backbone for interacting with Azure Blob Storage in .NET applications.

By understanding its role, key features, and methods, developers can effectively utilize its functionalities for creating, deleting, renaming, copying, and moving blob files.

Additionally, insights into error handling, asynchronous operations, and file metadata retrieval highlight best practices and enable developers to build scalable.

Let’s class should be with interface inject shared service “IFileOperationHelperService” and logger.

				
					public interface IFileOperationService
{
    Task CreateBlobFileFolderCreateAsync(string container, string filePath);
    Task DeleteBlobFilesAsync(string container, IList<string> filePaths);
    Task RenameBlobFileAsync(string containerName, string renamePath, string oldName, string newName);
    Task<bool> CopyBlobFilesAsync(string containerName, IList<string> oldFilePaths, string newFilePath);
    Task MoveBlobFilesAsync(string container, IList<string> oldFilePaths, string newFilePath);
    Task<IEnumerable<ContainerFileDTO>> GetFilesAsync(string container = "", string path = "");
    Task<FileDetailsDTO> GetFileDetailsAsync(string container, string path);
}
public class FileOperationService: IFileOperationService
{
   private readonly IFileOperationHelperService service;
   private readonly ILogger<FileOperationService> _logger;
    public FileOperationService(IFileOperationHelperService service,ILogger<FileOperationService> logger)
   {
 this.service = service;
 _logger = logger;
   }
}
				
			

GetFilesAsync provides a convenient way to retrieve blob files from Azure Blob Storage, offering flexibility to fetch files from specific containers or all containers.


Parameters:


It accepts two optional parameters: container (the name of the container to retrieve files from) and path (an optional path within the container to filter files).

Implementation:

  • If no container name is provided (container parameter is empty), it retrieves all containers using the GetContainersAsync method and iterates through each container to fetch its files

  • If a container name is provided, it calls the GetContainerFiles method to fetch files from the specified container and path

  • The retrieved files are added to a list (containerFiles)

  • Finally, the method returns a distinct list of container files to avoid duplicates.
				
					public record ContainerFileDTO(string Container,string File,string? Tier,long? Size,DateTimeOffset? CreatedOn,DateTimeOffset? ModifiedOn);
				
			
				
					public async Task<IEnumerable<ContainerFileDTO>> GetFilesAsync(string container = "", string path = "")
{
    var containerFiles = new List<ContainerFileDTO>();
 
    if (string.IsNullOrWhiteSpace(container))
    {
        var containers = await GetContainersAsync();
 
        foreach (string containerItem in containers)
        {
            var containerFileItems = GetContainerFiles(containerItem, null);
 
            containerFiles.AddRange(containerFileItems);
        }
    }
    else
    {
        var containerFileItems = GetContainerFiles(container, path);
 
        containerFiles.AddRange(containerFileItems);
    }
 
    return containerFiles.Distinct();
}
				
			

Here above method GetFilesAsync inside private method GetContainersAsync provides a convenient way to retrieve container names asynchronously, allowing applications to dynamically interact with containers in Azure Blob Storage.

				
					private async Task<IEnumerable<string>> GetContainersAsync()
{
    var containers = new List<string>();
 
    var blobServiceClient = service.CreateBlobServiceClient();
 
    await foreach (BlobContainerItem container in blobServiceClient.GetBlobContainersAsync())
    {
        containers.Add(container.Name);
    }
 
    return containers;
}
				
			

Here above method GetFilesAsync inside private GetContainerFiles offers a straightforward approach to retrieve and organize blob files from Azure Blob Storage, making it easier for applications to work with blob data efficiently.

ToMakePath extension method provides a simple and efficient way to generate relative paths for files based on a specified browse path, aiding in file navigation and organization.

				
					public static string ToMakePath(this string fileHeaderPath, string browsePath)
{
    var name = fileHeaderPath;
 
    if (name.StartsWith("/"))
    {
        name = name.Substring(1);
    }
 
    if (name.Contains("/"))
    {
        List<string> names = name.Split('/').ToList();
 
        if (browsePath.Contains("/"))
        {
            List<string> browsePaths = browsePath.Split("/").ToList();
 
            foreach (string item in browsePaths)
            {
                names.Remove(item);
            }
        }
        else
        {
            names.Remove(browsePath);
        }
 
        name = names.FirstOrDefault();
    }
 
    return name;
}
				
			

ToTrimLower method provides a convenient way to normalize strings, ensuring uniformity and facilitating string comparisons or processing in a consistent manner.

				
					public static string ToTrimLower(this string name)
{
    if (string.IsNullOrWhiteSpace(name)) return string.Empty;
 
    return name.Trim().ToLower();
}
				
			

IsActualFile method provides a simple way to determine whether a given file path represents an actual data file or a special file like a “Readme.md”

				
					public static bool IsActualFile(this string path)
{
    return !path.ToTrimLower().Contains("Readme.md");
}
				
			
				
					private IEnumerable<ContainerFileDTO> GetContainerFiles(string container, string path = "")
{
    var containerFiles = new List<ContainerFileDTO>();
 
    var blobServiceClient = service.CreateBlobServiceClient();
 
    BlobContainerClient containerClient = blobServiceClient.GetBlobContainerClient(container);
 
    var blobs = containerClient.GetBlobs();
 
    foreach (BlobItem blob in blobs)
    {
        string name = string.Empty;
 
        if (!string.IsNullOrWhiteSpace(path))
        {
            string fileName = blob.Name;
 
            if (fileName.Contains(path))
            {
                name = fileName.ToMakePath(path);
            }
        }
        else
        {
            if (blob.Name.Contains("/"))
            {
                name = blob.Name.Split("/").FirstOrDefault()!;
            }
            else
            {
                name = blob.Name;
            }
        }
 
        if (!string.IsNullOrWhiteSpace(name) && !containerFiles.Select(i => i.File.ToTrimLower()).Contains(name.ToTrimLower()))
        {
            string tier = string.Empty;
 
            if (blob.Properties.AccessTier.HasValue)
            {
                tier = blob.Properties.AccessTier.Value.ToString();
            }
 
            if (blob.Properties.ArchiveStatus != null && !string.IsNullOrEmpty(tier))
            {
                tier = $"{tier}({blob.Properties.ArchiveStatus.Value.ToString()})";
            }
 
            containerFiles.Add(new ContainerFileDTO(
            container,
            name,
            tier,
            blob.Properties.ContentLength,
            blob.Properties.CreatedOn,
            blob.Properties.LastModified));
        }
    }
 
    containerFiles = containerFiles.Where(i => i.File.IsActualFile()).ToList();
 
    return containerFiles.Distinct();
}
				
			

CopyBlobFilesAsync This asynchronous method facilitates the copying of blob files from one location to another within a specified container in Azure Blob Storage.

Purpose:

This asynchronous method facilitates the copying of blob files from one location to another within a specified container in Azure Blob Storage.

Implementation:

  • It iterates through each provided oldFilePath and asynchronously iterates through the blob items in the container matching the prefix

  • For each blob item, it constructs a new path (newPath) based on the provided newFilePath

  • It initiates an asynchronous copy operation from the source blob to the destination blob using StartCopyFromUriAsync

  • It logs an information message if the source blob does not exist and handles any exceptions using a try-catch block.
				
					public async Task<bool> CopyBlobFilesAsync(string container, IList<string> oldFilePaths, string newFilePath)
  {
      var blobServiceClient = service.CreateBlobServiceClient();
   
      var containerClient = blobServiceClient.GetBlobContainerClient(container);
   
      BlobClient destinationBlobClient;
   
      try
     {
         foreach (string oldFilePath in oldFilePaths)
         {
             await foreach (BlobItem blob in containerClient.GetBlobsAsync(prefix: oldFilePath))
             {
                 string blobPath = blob.Name;
  
                 BlobClient sourceBlobClient = containerClient.GetBlobClient(blobPath);
  
                 string newPath = blobPath;
  
                 if (oldFilePath.Contains("."))
                 {
                     if (blobPath.Contains("/"))
                     {
                         var oldFilePathSplit = blobPath.Split('/');
                         newPath = oldFilePathSplit[oldFilePathSplit.Length - 1];
                     }
                 }
                 else
                 {
                     newPath = oldFilePath;
  
                     if (oldFilePath.Contains("/"))
                     {
                         var oldFilePathSplit = oldFilePath.Split("/");
                         newPath = oldFilePathSplit[oldFilePathSplit.Length - 1];
                     }
  
                     newPath = blobPath.Substring(blobPath.IndexOf(newPath));
                 }
  
                 if (!string.IsNullOrWhiteSpace(newFilePath))
                 {
                     newPath = $"{newFilePath}/{newPath}";
                 }
  
                 if (await sourceBlobClient.ExistsAsync())
                 {
                     destinationBlobClient = containerClient.GetBlobClient(newPath);
  
                     await destinationBlobClient.StartCopyFromUriAsync(sourceBlobClient.Uri);
                 }
                 else
                 {
                     _logger.LogInformation("Source blob does not exist.");
                 }
             }
         }
  
         return true;
     }
     catch (RequestFailedException ex)
     {
         _logger.LogError($"Error: {ex.Message}");
     }
  
     return false;
 }

				
			

RenameBlobFileAsync renames a blob file within a specified container in Azure Blob Storage. Here’s a concise explanation:

Purpose:

It renames a blob file by replacing occurrences of the oldName with the newName in blob names matching the provided renamePath.

Implementation:

  • It retrieves a BlobServiceClient instance using the CreateBlobServiceClient method of the service object

  • It obtains the BlobContainerClient for the specified container

  • It asynchronously iterates through blob items in the container matching the provided renamePath

  • For each blob item, it constructs the new blob name by replacing occurrences of the oldName with the newName

  • It initiates an asynchronous copy operation from the source blob to the destination blob using StartCopyFromUriAsync

  • After successful copying, it deletes the source blob using DeleteIfExistsAsync

  • It logs an error message if the source blob does not exist
				
					public async Task RenameBlobFileAsync(string containerName, string renamePath, string oldName, string newName)
{
    var blobServiceClient = service.CreateBlobServiceClient();
 
    var containerClient = blobServiceClient.GetBlobContainerClient(containerName);
 
    await foreach (BlobItem blob in containerClient.GetBlobsAsync(prefix: renamePath))
    {
        string oldBlobName = blob.Name;
 
        string newBlobName = oldBlobName.Replace(oldName, newName.Trim());
 
        if (oldBlobName.Equals(newBlobName))
        {
            return;
        }
 
        BlobClient sourceBlobClient = containerClient.GetBlobClient(oldBlobName);
 
        if (await sourceBlobClient.ExistsAsync())
        {
            BlobClient destinationBlobClient = containerClient.GetBlobClient(newBlobName);
 
            await destinationBlobClient.StartCopyFromUriAsync(sourceBlobClient.Uri);
 
            await sourceBlobClient.DeleteIfExistsAsync();
        }
        else
        {
            _logger.LogError($"Source blob '{blob.Name}' doesn't exist.");
        }
    }
}
				
			

MoveBlobFilesAsync moves blob files from one location to another within a specified container in Azure Blob Storage. Here’s a concise explanation:

Purpose:

It moves blob files by first copying them to a new location using CopyBlobFilesAsync and then deleting the original files using DeleteBlobFilesAsync.

Implementation:

  • It asynchronously copies blob files from oldFilePaths to the newFilePath within the specified container using CopyBlobFilesAsync

  • If the copying is successful (copiedFile is true), it asynchronously deletes the original files from oldFilePaths using DeleteBlobFilesAsync
				
					public async Task MoveBlobFilesAsync(string container, IList<string> oldFilePaths, string newFilePath)
{
    var copiedFile = await CopyBlobFilesAsync(container, oldFilePaths, newFilePath);
 
    if (copiedFile)
    {
        await DeleteBlobFilesAsync(container, oldFilePaths);
    }
}
				
			

GetFileDetailsAsync retrieves details of a specific blob file within a specified container in Azure Blob Storage. Here’s an explanation:

Purpose:

It fetches details such as name, last modified date, size, content type, and metadata of a blob file located at the given path within the specified container.

Implementation:

  • It initializes a FileDetailsDTO object to store the details of the blob file

  • It creates a BlobServiceClient instance using the CreateBlobServiceClient method of the service object

  • It obtains the BlobContainerClient for the specified container

  • It asynchronously iterates through blob items in the container matching the provided path

  • For each matching blob item, it constructs a BlobClient to interact with the blob

  • It retrieves properties of the blob using GetPropertiesAsync() method, including metadata

  • It populates the FileDetailsDTO object with details extracted from the blob properties

  • It breaks the loop after processing the first matching blob item to retrieve details for a specific file

SelectLookup<T> is a versatile data structure suitable for storing and passing around key-value pairs, offering simplicity, immutability, and type safety.

				
					public record SelectLookup<T>(T Key,string Value);
				
			

FileDetailsDTO record provides a structured way to represent the details of a blob file, including its name, size, type, last modified date, and additional metadata, making it suitable for transferring file information within applications interacting with Azure Blob Storage.

				
					public record FileDetailsDTO
{
    public string Name { get; init; }
    public long Size { get; init; }
    public string Type { get; init; }
    public string Date { get; init; }
    public IEnumerable<SelectLookup<string>> Metadatas { get; init; }
}
				
			

Now the code is

				
					public async Task<FileDetailsDTO> GetFileDetailsAsync(string container, string path)
{
    var fileDetail = new FileDetailsDTO();
 
    var blobServiceClient = service.CreateBlobServiceClient();
 
    var containerClient = blobServiceClient.GetBlobContainerClient(container);
 
    await foreach (BlobItem blob in containerClient.GetBlobsAsync(prefix: path))
    {
        var blobClient = containerClient.GetBlobClient(blob.Name);
 
        var properties = await blobClient.GetPropertiesAsync();
 
        fileDetail = new FileDetailsDTO
        {
            Name = blob.Name,
            Date = blob.Properties.LastModified.Value.UtcDateTime.ToString(),
            Size = blob.Properties.ContentLength ?? 0,
            Type = blob.Properties.ContentType,
            Metadatas = properties.Value.Metadata
                .Select(i => new SelectLookup<string>(i.Key, i.Value))
        };
 
        break;
    }
 
    return fileDetail;
}
				
			

CreateBlobFileFolderCreateAsync method is responsible for creating a file (specifically a Markdown file named “Readme.md”) within a folder (or directory) in a specified container within Azure Blob Storage. Here’s an explanation of the method:

Purpose:

This method is designed to create a Markdown file named “Readme.md” within a specified folder path in the Azure Blob Storage container.

Implementation:

  • It modifies the filePath parameter by appending “/Readme.md” to it. This ensures that the file will be created with the desired name and within the specified folder structure

  • It obtains a BlobServiceClient instance using the CreateBlobServiceClient method of the service object

  • It retrieves the BlobContainerClient for the specified container from the blobServiceClient

  • It ensures that any existing file at the specified filePath is deleted using the DeleteBlobFileAsync method (not shown here), ensuring that the file is created anew

  • It obtains a BlobClient representing the file blob within the folder using the GetBlobClient method of the containerClient

  • It initializes a MemoryStream to contain the content of the file (which is empty in this case since the file is just being created)

  • It uploads the content (in this case, an empty stream) to the blob representing the file within the folder using the UploadAsync method

  • It logs an informational message confirming the successful creation of the file with the specified filePath


The code is

				
					public async Task CreateBlobFileFolderCreateAsync(string container, string filePath)
{
 
    filePath = $"{filePath}/Readme.md";
 
    var blobServiceClient = service.CreateBlobServiceClient();
 
    var containerClient = blobServiceClient.GetBlobContainerClient(container);
 
    await DeleteBlobFileAsync(container, filePath);
 
    var folderBlob = containerClient.GetBlobClient(filePath);
 
    using (MemoryStream stream = new MemoryStream())
    {
        await folderBlob.UploadAsync(stream);
 
        _logger.LogInformation($"File '{filePath}' created.");
    }
}
				
			

GetFileDetailsAsync method retrieves details about a specific file stored in an Azure Blob Storage container. Here’s a concise explanation of its functionality:

Purpose:

The method fetches metadata and properties of a file stored in the Azure Blob Storage container specified by the container parameter and located at the path specified by the path parameter.

Implementation:

  • It initializes a new instance of FileDetailsDTO to store the details of the file

  • It obtains a BlobServiceClient instance using the CreateBlobServiceClient method of the service object

  • It retrieves the BlobContainerClient corresponding to the specified container from the blobServiceClient

  • It iterates asynchronously over the blobs in the container using await foreach

  • Within the loop, it obtains a BlobClient representing the current blob

  • It retrieves properties of the blob, such as its name, last modified date, content length, content type, and metadata, using the GetPropertiesAsync method

  • It initializes the fileDetail object with the retrieved properties, including the blob name, last modified date converted to UTC string, content length, content type, and metadata represented as SelectLookup<string> instances

  • It breaks out of the loop after processing the first blob, assuming that the specified path uniquely identifies a single file. If multiple blobs match the prefix, only details of the first blob are fetched

The code is

				
					public async Task<FileDetailsDTO> GetFileDetailsAsync(string container, string path)
{
    var fileDetail = new FileDetailsDTO();
 
    var blobServiceClient = service.CreateBlobServiceClient();
 
    var containerClient = blobServiceClient.GetBlobContainerClient(container);
 
    await foreach (BlobItem blob in containerClient.GetBlobsAsync(prefix: path))
    {
        var blobClient = containerClient.GetBlobClient(blob.Name);
 
        var properties = await blobClient.GetPropertiesAsync();
 
        fileDetail = new FileDetailsDTO
        {
            Name = blob.Name,
            Date = blob.Properties.LastModified.Value.UtcDateTime.ToString(),
            Size = blob.Properties.ContentLength ?? 0,
            Type = blob.Properties.ContentType,
            Metadatas = properties.Value.Metadata
                .Select(i => new SelectLookup<string>(i.Key, i.Value))
        };
 
        break;
    }
 
    return fileDetail;
}
				
			

Step 8: Now our all service method is ready, Let’s create an API controller belonging to all service methods and create an endpoint.

The controller name as “FileOperationController” inject the necessary dependency “IFileOperationService”

				
					[ApiController]
[Route("[controller]")]
public class FileOperationController : ControllerBase
{
    private readonly IFileOperationService _service;
 
    public FileOperationController(IFileOperationService service)
    {
        _service = service;
    }
}
				
			

Get Endpoint “GetFiles”: Create a query payload

				
					public record GetFileQuery(string Container,string Path="");
				
			

And the method is

				
					[HttpGet("GetFiles", Name = "GetFiles")]
public async Task<IActionResult> GetFiles([FromQuery] GetFileQuery fileQueryDTO)
{
    var response = await _service.GetFilesAsync(fileQueryDTO.Container, fileQueryDTO.Path);
 
    return Ok(response);
}
				
			

Get Endpoint “GetFileDetails”: Create a payload

				
					public record FileDetailsQuery
{
    public string Container { get; init; }
    public string Path { get; init; }
}
				
			

And the method is

				
					[HttpGet("GetFileDetails", Name = "GetFileDetails")]
public async Task<IActionResult> GetFileDetails([FromQuery] FileDetailsQuery query)
{
    var response = await _service.GetFileDetailsAsync(query.Container, query.Path);
 
    return Ok(response);
}
				
			

Post Endpoint “CreateBlobFileFolder”: Create a command

				
					public record CreateFileCommand(string Container,string FilePath);
				
			

And the method is

				
					[HttpPost("CreateBlobFileFolder", Name = "CreateBlobFileFolder")]
public async Task<IActionResult> CreateBlobFileFolder([FromBody] CreateFileCommand command)
{
    await _service.CreateBlobFileFolderCreateAsync(command.Container, command.FilePath);
 
    return Ok(true);
}
				
			

Post Endpoint “DeleteBlobFiles”: Create a command

				
					public record DeleteFileCommand(string Container,IList<string> Paths);
				
			

And the method is

				
					[HttpPost("DeleteBlobFiles", Name = "DeleteBlobFiles")]
public async Task<IActionResult> DeleteBlobFiles([FromBody] DeleteFileCommand command)
{
    await _service.DeleteBlobFilesAsync(command.Container, command.Paths);
 
    return Ok(true);
}
				
			

Post Endpoint “RenameBlobFile”: Create a command

				
					public record RenameFileCommand(string Container,string RenamePath,string OldName,string NewName);
				
			

And the method is

				
					[HttpPost("RenameBlobFile", Name = "RenameBlobFile")]
public async Task<IActionResult> RenameBlobFile([FromBody] RenameFileCommand command)
{
    await _service.RenameBlobFileAsync(command.Container, command.RenamePath, command.OldName, command.NewName);
 
    return Ok(true);
}
				
			

Post Endpoint “CopyBlobFiles”: Create a command

				
					public record CopyFileCommand(string Container,IList<string> OldFilePaths,string NewFilePath);
				
			

And the method is

				
					[HttpPost("CopyBlobFiles", Name = "CopyBlobFiles")]
public async Task<IActionResult> CopyBlobFiles([FromBody] CopyFileCommand command)
{
    await _service.CopyBlobFilesAsync(command.Container, command.OldFilePaths, command.NewFilePath);
 
    return Ok(true);
}
				
			

Post Endpoint “MoveBlobFiles”: Create a command if not exist.

				
					public record CopyFileCommand(string Container,IList<string> OldFilePaths,string NewFilePath);
				
			

And the method is

				
					[HttpPost("MoveBlobFiles", Name = "MoveBlobFiles")]
public async Task<IActionResult> MoveBlobFiles([FromBody] CopyFileCommand command)
{
    await _service.MoveBlobFilesAsync(command.Container, command.OldFilePaths, command.NewFilePath);
 
    return Ok(true);
}
				
			

Step 9: Now the final solution look like this

All class files of Mastering .NET for Azure blob files reading and writing project

Now let’s have a look at the Properties -> LaunchSettings.json and follow https api url.

				
					{
  "profiles": {
    "http": {
      "commandName": "Project",
      "launchBrowser": true,
      "launchUrl": "swagger",
      "environmentVariables": {
        "ASPNETCORE_ENVIRONMENT": "Development"
      },
      "dotnetRunMessages": true,
      "applicationUrl": "http://localhost:5161"
    },
    "https": {
      "commandName": "Project",
      "launchBrowser": true,
      "launchUrl": "swagger",
      "environmentVariables": {
        "ASPNETCORE_ENVIRONMENT": "Development"
      },
      "dotnetRunMessages": true,
      "applicationUrl": "https://localhost:7074;http://localhost:5161"
    },
    "IIS Express": {
      "commandName": "IISExpress",
      "launchBrowser": true,
      "launchUrl": "swagger",
      "environmentVariables": {
        "ASPNETCORE_ENVIRONMENT": "Development"
      }
    },
    "Container (Dockerfile)": {
      "commandName": "Docker",
      "launchBrowser": true,
      "launchUrl": "{Scheme}://{ServiceHost}:{ServicePort}/swagger",
      "environmentVariables": {
        "ASPNETCORE_HTTPS_PORTS": "8081",
        "ASPNETCORE_HTTP_PORTS": "8080"
      },
      "publishAllPorts": true,
      "useSSL": true
    }
  },
  "$schema": "http://json.schemastore.org/launchsettings.json",
  "iisSettings": {
    "windowsAuthentication": false,
    "anonymousAuthentication": true,
    "iisExpress": {
      "applicationUrl": "http://localhost:18402",
      "sslPort": 44330
    }
  }
}

				
			

Let’s run the application and output will be

API Endpoints of project

Let’s check the GetFiles Endpoint. In my case i use a “sitefile” container. path will be empty. If give specific path it will return specific path result.

Endpoint : GetFiles

In the storage explorer application, the files within the ‘sitefile’ container are as follows in my scenario.

All uploaded files in sitefile folder in storage explorer

Let’s check the GetFileDetails Endpoint. Give the container name and path.

Endpoint : GetFileDetails

Let’s check the CreateBlobFileFolder Endpoint. Give the container name and the folder name which you want to create.

Endpoint: CreateBlobFileFolder

Check storage explorer if this folder is created or not.

Create my new folder in storage explore

Let’s check DeleteBlobFiles Endpoint. Provide container name and path list in this endpoint.

Endpoint : DeleteBlobFiles

Let’s check the RenameBlobFile Endpoint. Give container name, rename path, old name and new name and rename path could be your_path/your_sub_path/your_file. In my case my file is inside of the container. that’s why I give only the file name.

Endpoint: RenameBlobFile

Check the storage explorer. If file rename or not.

Create newname.tif in storage explorer

Let’s check the CopyBlobFiles. Give the container name. Then give old file paths where you want to copy files. And give a new file path and paste all copied files.

Endpoint : CopyBlobFiles

Check also the storage explorer if the file is copied or not.

Copied NewName.tif file to my new folder in storage explorer

Let’s check MoveBlobFiles endpoint. Give container names and also old file paths and new file paths as well.

Endpoint: MoveBlobFiles

Check the storage explorer if the file moved or not.

Check if the NewName.tif already moved from my new folder in storage explorer
Check if the NewName.tif shown in sitefile folder in storage explorer

Conclusion

In conclusion, this blog provides a comprehensive guide to performing file operations in Azure Blob Storage using .NET. It covers various essential aspects such as creating, copying, moving, and deleting files, as well as retrieving file details.

The blog includes detailed explanations of code snippets, prerequisites, and example steps for using the .NET API to interact with Azure Blob Storage.

By following this guide, readers can gain a solid understanding of how to effectively manage files within Azure Blob Storage using .NET, empowering them to develop robust and scalable applications leveraging cloud storage capabilities.

Potential Developer
Tech Stack
0 +
Accelerate Your Software Development Potential with Us
With our innovative solutions and dedicated expertise, success is a guaranteed outcome. Let's accelerate together towards your goals and beyond.
Blogs You May Love

Don’t let understaffing hold you back. Maximize your team’s performance and reach your business goals with the best IT Staff Augmentation