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

Time:04-28

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

CodePudding user response:

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();

CodePudding user response:

The problem is that you start the copy operation but don't wait for it to finish. Instead, you delete the file that is the source op the copy operation

file.StartCopy(fileSas);

This call starts the copy operation. It runs in the background. It returns a ShareFileCopyInfo instance you can inspect to see the status of the operation. The property CopyStatus is an enum with the values Aborted, Failed, Pending and Success, see the docs.

I suspect in your case the operation is still pending when you call blobClient.Delete();.

According to the official example you could do this to await completion of the Copy operation:

        // Start the copy operation
        file.StartCopy(fileSas);

        if (await file.ExistsAsync())
        {
            Console.WriteLine($"{sourceFile.Uri} copied to {destFile.Uri}");
        }

Another option is to poll for completion.

  • Related