如何使用Azure Storage SDK将Azure文件存储中的文件从一个子文件夹移动到另一个子文件夹?

13
我正在尝试弄清楚如何将Azure文件存储中的文件从一个位置移动到同一共享中的另一个位置。
例如:
source -> \\Share1\someFile.txt
destination -> \\Share1\Foo\Bar\someFile.txt
  • 我需要先复制文件,再删除源文件吗?
  • 如果目标子目录不存在怎么办?我需要为每个子目录首先使用CreateIfNotExistsAsync吗?

干杯!

7个回答

12
这是在Azure存储文件的入门指南中记录的参考文献。您需要使用StartCopy方法将文件从一个位置复制到另一个位置。
// Start the copy operation.
destinationFile.StartCopy(sourceFile);

是的,如果目标目录不存在,您将需要创建它。


11

像这样:

public static void MoveTo(this CloudFile source, CloudFileDirectory directory)
{
    var target = directory.GetFileReference(source.Name);
    target.StartCopy(source);
    source.Delete();
}

1
这很完美! - Casey Crookston
1
(虽然我添加了一个“bool deleteOriginal”参数):) - Casey Crookston
这不是叫做移动吗?不是复制吗?;-) 只是开玩笑。 - Jerry Nixon

3

很遗憾,我们的REST API没有公开的移动/重命名功能,而客户端SDK是依赖于该API的。当然,您可以通过SMB执行这些功能。我们已经将这些功能放入待办列表中,但目前还没有具体的实施时间表。


3
这是我公司代码库的一个重要特性。如果无法将应用程序“移动”到子目录中,那么我就无法可靠地将本地应用程序移植过来,因为这是应用程序架构和工作流程的关键部分。最让人沮丧的是,这显然存在于SMB接口中。备选方案是能够在Azure函数应用程序中暂时挂载一个SMB驱动器,然后我可以使用传统的文件IO概念通过System.IO和SMB 3在Azure中实现所有目标。 - Sql Surfer
具有讽刺意味的是,除了我仅用于从云端通过 VPN 回到我的本地服务器农场进行文件访问和在同一驱动器和共享之间执行 MOVE 操作的 Azure 应用程序之外,我完全是 Azure 的 100%。我们喜欢在 Azure 中没有虚拟机,因此我采用 PaaS。 - Sql Surfer

3
这是针对Asp.net Core 3+的更新答案,使用新的Blob API。您可以使用BlockBlobClientStartCopyFromUriAsync,如果想要等待完成,则使用WaitForCompletionAsync
var blobServiceClient = new BlobServiceClient("StorageConnectionString");
var containerClient = blobServiceClient.GetBlobContainerClient(container);
var blobs = containerClient.GetBlobs(BlobTraits.None, BlobStates.None, sourceFolder);

await Task.WhenAll(blobs.Select(async blob =>
{
    var targetBlobClient = containerClient.GetBlockBlobClient($"{targetFolder}/{blob.Name}");
    var blobUri = new Uri($"{containerClient.Uri}/{blob.Name}");
    var copyOp = await targetBlobClient.StartCopyFromUriAsync(blobUri);
    return await copyOp.WaitForCompletionAsync();
}).ToArray());

或者,如果您不需要等待完成并且只想“点火并忘记”。
foreach (var blob in blobs)
{
    var targetBlobClient = containerClient.GetBlockBlobClient($"{targetFolder}/{blob.Name}");
    var blobUri = new Uri($"{containerClient.Uri}/{blob.Name}");
    targetBlobClient.StartCopyFromUriAsync(blobUri);
}

哦,这很好!你必须使用WaitForCompletionAsync吗?还是可以随便 "fire and forget"(发射和忘记)?此外,请问你能提供文档链接吗? - Pure.Krome
1
你可以点火并忘记它。我更新了答案以展示两个选项。 - Ryan Langton
你需要使用await关键字来等待“fire and forget”版本的StartCopyFromUriAsync方法吗?还是直接返回任务,但不执行任何操作呢? - Pure.Krome
我猜你可以等待它,那就是等待“开始”操作完成。 - Ryan Langton

1
Azure 存储文件共享是兼容 SMB 的共享,因此您应该能够使用普通的文件 I/O 操作进行文件复制/移动。这与直接操作 blob 不同,后者需要通过存储 API 明确创建容器、启动 blob 复制等。

“使用常规的文件输入/输出操作”<- 你是在说...通过System.File.IO命名空间,我可以使用那个命名空间下的方法吗?实际上,我正在使用官方的存储软件开发工具包(SDK),并且想要继续使用该存储SDK库中的方法。 - Pure.Krome
@Pure.Krome - 是的 - 这正是我想说的。引用自这篇文章中的话: “您可以从命令提示符发出标准文件命令,或者从文件资源管理器中查看已挂载的共享及其内容。您还可以在虚拟机内运行代码,使用标准的Windows文件I/O API访问文件共享,例如.NET Framework中提供的System.IO命名空间中的API。” - David Makogon
真让人开心 - 我还以为你说过这些了。你所说的全部都是在尝试通过挂载访问文件存储时才需要考虑的。那是一个虚拟磁盘(也就是SMB)。我不想要一个挂载点,而且我也没有任何一个。因为我没有本地挂载点,所以我不能使用“System.File.IO”中的任何东西。其次,即使我有挂载点,使用SMB比使用REST端点更慢(参考:https://dev59.com/n5ffa4cB1Zd3GeqP-qPv)。所以 - 我正在尝试通过SDK来解决这个问题(正如OP所提到的)。 - Pure.Krome
好的。所以,只是为了明确:SMB挂载不同于虚拟磁盘(vhd)。而且你最初的问题标记为Azure文件。所以我可能误解了问题。对此我很抱歉。 - David Makogon
不客气。对了,我指的是虚拟磁盘,比如c/d/z等抽象概念……并非真正的VHD。再次抱歉用词不当。 - Pure.Krome
你有没有研究过Azure Files的REST API?https://msdn.microsoft.com/zh-cn/library/azure/mt427372.aspx - Mine Tanrinian Demir - MSFT

0
在Azure门户中,选择“重命名”选项,然后提供文件夹名称\文件名称,这对我解决了类似的问题。

目前您的回答表达不够清晰。请[编辑]以添加更多细节,帮助其他人理解您的回答如何解决所提出的问题。您可以在帮助中心找到更多有关如何撰写好答案的信息。 - undefined

-1
Azure Blob的子目录是虚拟的,它们并不存在于物理上,blob/文件的名称包含了完整的路径。因此,您不必显式地“创建”该目录。
我认为Azure Blob/文件没有原子性的“重命名”方法...要避免这种情况,您需要复制(使用新名称)然后删除原始文件。

1
此指南仅适用于 Blob,不适用于 Azure 文件存储(它在 Blob 存储之上实现了 SMB 共享,并且这正是 OP 特别询问的内容)。 - David Makogon
我刚刚尝试了Azure文件存储,并将文件重命名为目标目录中的文件路径,这使得它在我的笔记本电脑上的Windows资源管理器以及我的Azure门户存储帐户的资源管理器中按预期显示。https://learn.microsoft.com/en-us/dotnet/api/azure.storage.files.shares.sharefileclient.rename - Tony

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接