Hello and welcome to this blog which shows you how to copy files and folders with the same hierarchy from Azure blob to Azure file share using c#. This article lets you copy files without downloading them to the local system. So, without further delay, will dive directly into a code snippet.
First, connect to the container using the connection string and get the container reference from where the files are to be copied.
private BlobContainerClient GetBlobContainerClient()
{
BlobServiceClient blobServiceClient = new BlobServiceClient("Storage-connection-string-from-Azure");
return blobServiceClient.GetBlobContainerClient("container-name");
}
After getting the container reference, the next step is to list all the blobs inside the container
public async IAsyncEnumerable<BlobClient> GetAllBlobsAsync(string prefix) // prefix : folder under a container to list the files
{
var container = GetBlobContainerClient();
await foreach (BlobItem page in container.GetBlobsAsync(BlobTraits.None, BlobStates.None, prefix))
{
yield return container.GetBlobClient(page.Name);
}
}
Then loop through the blobs to copy to Azure file share as below. We fetch the URI for each file/blob and pass it to the file share service to copy.
public async Task ImportDocsFromBlobToFileShare(string blobName)
{
IAsyncEnumerable<BlobClient> lstBlobClients = _blobService.GetAllBlobsAsync(blobName);
await foreach (var item in lstBlobClients)
{
Uri blobSas = item.GenerateSasUri(
Azure.Storage.Sas.BlobSasPermissions.Read,
DateTime.UtcNow.AddHours(2)
); // SAS Uri is optional
await _fileShareService.CopyFromURI(blobSas, item.Name);
}
}
public async Task CopyFromURI(Uri uri, string fileName)
{
ShareClient shareClient = new ShareClient(
fileShareConnectionString,
fileShareName
); // connect to azure file share with connection string and file share name
ShareDirectoryClient targetDirectoryClient = await GetSubDirectory(shareClient, uri);
// if the file is under nested folders, create those folders first and copy the file.
ShareFileClient fileClient = targetDirectoryClient.GetFileClient(
fileName.Substring(fileName.LastIndexOf('/') + 1)
);
await fileClient.StartCopyAsync(uri);
}
private async Task<ShareDirectoryClient> GetSubDirectory(ShareClient shareClient, Uri uri)
{
ShareDirectoryClient shareDirectoryClient = shareClient.GetRootDirectoryClient();
var directories = uri.AbsolutePath
.Trim('/')
.Split('/')
.SkipLast(1); // this skip is to exclude the file name and just fetch directory hierarchy
foreach (string directory in directories)
{
shareDirectoryClient = shareDirectoryClient.GetSubDirectoryClient(directory);
await shareDirectoryClient.CreateIfNotExistsAsync();
}
return shareDirectoryClient;
}
That's it....and you are good to go. This worked like a charm to me. May be we can fine tune this, but this does serve the purpose.