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:
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.