Search code examples
c#azureazure-blob-storageazure-storage

How to fix sending data from blob to fileshare within same storage account?


I am trying to send data from Blob container to File share and this is the code I am using but surprisingly it is not working:

public static void MoveFileBlobToFileShare(string shareName, string fileName, string sourceDirName, string destinationDirName, string container, string destinationFileName = "")
{
var blobServiceClient = Zeus.AzureStorage.Common.CreateblobServiceClient();
            var containerClient = blobServiceClient.GetBlobContainerClient(container);
            var blobClient = containerClient.GetBlobClient(sourceDirName + "/" + fileName);
            var fileSas = blobClient.GenerateSasUri(Azure.Storage.Sas.BlobSasPermissions.Read, DateTime.UtcNow.AddHours(24));
            var shareClient = Common.CreateSMBClientFromConnectionString(shareName);
            ShareDirectoryClient directory = shareClient.GetDirectoryClient(destinationDirName);
            ShareFileClient file = string.Equals(string.Empty, destinationFileName) ?
                directory.GetFileClient(fileName) : directory.GetFileClient(destinationFileName);
            file.StartCopy(fileSas);
            blobClient.Delete();
}

Is there anyway to just use blobClient.URI and get rid of fileSAS

Error I am receiving:

The specified blob does not exist.
RequestId:b19857e0-001a-0008-670a-5a8332000000
Time:2022-04-27T07:46:55.4219904Z
Status: 404 (The specified blob does not exist.)
ErrorCode: CannotVerifyCopySource

Content:
<?xml version="1.0" encoding="utf-8"?><Error><Code>CannotVerifyCopySource</Code><Message>The specified blob does not exist.
RequestId:b19857e0-001a-0008-670a-5a8332000000
Time:2022-04-27T07:46:55.4219904Z</Message></Error>

Headers:
x-ms-request-id: b19857e0-001a-0008-670a-5a8332000000
x-ms-client-request-id: 697e573f-1ef0-47e5-971e-97f67b4fa083
x-ms-version: 2021-04-10
x-ms-error-code: CannotVerifyCopySource
Content-Length: 225
Content-Type: application/xml
Date: Wed, 27 Apr 2022 07:46:55 GMT
Server: Windows-Azure-File/1.0 Microsoft-HTTPAPI/2.0

Solution

  • Is there anyway to just use blobClient.URI and get rid of fileSAS

    While using Microsoft.WindowsAzure.Storage one of the workaround is to generate SAS and then use the below code to get the Uri.

    Uri blobSASUri = new Uri(sourceBlob.StorageUri.PrimaryUri.ToString() + blobSAS);
    

    If you are using Azure.Storage.Blobs then the below works

    string sasuri = "<SAS>";
    Uri blobUri = new Uri(sasuri);
    

    Below is the code that worked for us to transfer files from Blob Storage to Fileshares using WindowsAzure.Storage.

    static async Task Main(string[] args)
            {
                CloudStorageAccount storageAccount = CloudStorageAccount.Parse("<Connection_String>");
    
                // To get Blob References
                var blobClient = storageAccount.CreateCloudBlobClient();
                CloudBlobContainer cloudBlobContainer = blobClient.GetContainerReference("container1");
                CloudBlockBlob sourceBlob = cloudBlobContainer.GetBlockBlobReference("TextSample.txt");
    
                // To get FileShare References
                CloudFileClient cloudFileClient = storageAccount.CreateCloudFileClient();
                CloudFileShare cloudFileShare = cloudFileClient.GetShareReference("fileshare1");
                CloudFile destinationFileShare = cloudFileShare.GetRootDirectoryReference().GetFileReference("TextSample.txt");
    
                // Generating SAS
                string blobSAS = sourceBlob.GetSharedAccessSignature(new SharedAccessBlobPolicy()
                {
                    Permissions = SharedAccessBlobPermissions.Read,
                    SharedAccessExpiryTime = DateTime.UtcNow.AddHours(24)
                });
    
                // Copying Blob To FileShare
                Uri blobSASUri = new Uri(sourceBlob.StorageUri.PrimaryUri.ToString() + blobSAS);
                await destinationFileShare.StartCopyAsync(blobSASUri);
    
                // Deleting when Transfer is done
                await sourceBlob.DeleteIfExistsAsync();
                Console.WriteLine("Transfer Complete!");
            }
    

    Below is the code worked when Azure.Storage.blob is used.

    static async Task Main(string[] args)
            {
                // To get Blob References
                BlobServiceClient serviceClient = new BlobServiceClient("<Connection_String>");
                BlobContainerClient containerClient = serviceClient.GetBlobContainerClient("container1");
                BlobClient sourceBlob = containerClient.GetBlobClient("TextSample.txt");
    
                // To get FileShare References
                ShareFileClient destinationFileShare = new ShareFileClient("<Connection_String>", "fileshare1", "TextSample.txt");
    
                // Generating SAS
                Uri blobSAS = sourceBlob.GenerateSasUri(Azure.Storage.Sas.BlobSasPermissions.Read, DateTime.UtcNow.AddHours(24));
    
                // Copying Blob To FileShare
                await destinationFileShare.StartCopyAsync(blobSAS);
    
                // Deleting when Transfer is done
                await sourceBlob.DeleteIfExistsAsync();
                Console.WriteLine("Completed Trasfer!");
            }
    

    RESULT:

    enter image description here

    updated Answer

    BlobServiceClient blobServiceClient = new BlobServiceClient("<ConnectionString>");
    
    var containerClient = blobServiceClient.GetBlobContainerClient(container);
    var blobClient = containerClient.GetBlobClient(sourceDirName + "/" + fileName);
    var fileSas = blobClient.GenerateSasUri(Azure.Storage.Sas.BlobSasPermissions.Read, DateTime.UtcNow.AddHours(24));
    
    ShareClient shareClient = new ShareClient("<ConnectionString>", shareName);
    ShareDirectoryClient directory = shareClient.GetDirectoryClient(destinationDirName);
    ShareFileClient file = string.Equals(string.Empty, destinationFileName) ? directory.GetFileClient(fileName) : directory.GetFileClient(destinationFileName);
    file.StartCopy(fileSas);
    blobClient.Delete();