如何修复在同一存储帐户中将数据从 blob 发送到文件共享?

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

我正在尝试将数据从 Blob 容器发送到文件共享,这是我正在使用的代码,但令人惊讶的是它不起作用:

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

有没有办法只使用 blobClient.URI 并摆脱 fileSAS

我收到的错误:

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

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

使用 Microsoft.WindowsAzure.Storage 时,解决方法之一是生成 SAS,然后使用以下代码获取 Uri。

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

如果您使用的是 Azure.Storage.Blobs,则以下内容有效

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

下面是我们使用 WindowsAzure.Storage.

将文件从 Blob 存储传输到 Fileshares 的代码
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!");
        }

下面是使用 Azure.Storage.blob 时的代码。

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!");
        }

结果:

更新答案

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

问题是您开始复制操作但没有等待它完成。相反,您删除作为复制操作源操作的文件

file.StartCopy(fileSas);

此调用启动复制操作。它在后台运行。它returns一个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.

我怀疑在您的情况下,当您调用 blobClient.Delete();.

时,操作仍在等待中

根据 the official example,您可以这样做以等待复制操作完成:

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

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

另一种选择是轮询完成。