你当前正在访问 Microsoft Azure Global Edition 技术文档网站。 如果需要访问由世纪互联运营的 Microsoft Azure 中国技术文档网站,请访问 https://docs.azure.cn

通过数据移动库传输数据

Azure 存储数据移动库是一个高性能的跨平台开源库,用于上传、下载和复制 Blob 与文件。 数据移动库提供用于 .NET 的 Azure 存储客户端库中不能提供的便利方法。 通过这些方法,可以设置并行操作的数量、跟踪传输进度、恢复已取消的传输等。

数据移动库仅适用于 .NET,并且仅支持 Azure Blob 存储和 Azure 文件。 在决定是否使用数据移动库时,应考虑这些限制以及其他已知问题

如果要将代码从旧版 Microsoft.Azure.Storage.DataMovement库(版本 2.X.X)迁移到当前 Azure.Storage.DataMovement 库(版本 12.X.X),请参阅迁移指南

API 参考文档 | 源代码 | 包 (NuGet) | 示例:Blob / Files.Shares

先决条件

设置你的环境

如果没有现有项目,请查看本部分,其中介绍如何设置项目来使用适用于 .NET 的 Azure Blob 存储客户端库。 步骤包括安装包、添加 using 指令,以及创建已授权的客户端对象。

安装包

在项目目录中,使用 dotnet add package 命令安装适用于 Azure 存储数据移动客户端库和 Azure 标识客户端库的包。 与 Azure 服务建立无密码连接需要 Azure.Identity 包

dotnet add package Azure.Storage.DataMovement
dotnet add package Azure.Storage.DataMovement.Blobs
dotnet add package Azure.Identity

若要使用适用于 Azure 文件的扩展库,请安装 Azure.Storage.DataMovement.Files.Shares 包:

dotnet add package Azure.Storage.DataMovement.Files.Shares

添加 using 指令

若要运行本文中的代码示例,请添加以下 using 指令:

using Azure;
using Azure.Core;
using Azure.Identity;
using Azure.Storage.DataMovement;
using Azure.Storage.DataMovement.Blobs;

如果你使用的是适用于 Azure 文件的扩展库,请添加以下 using 指令:

using Azure.Storage.DataMovement.Files.Shares;

授权

授权机制必须具有执行上传、下载或复制操作所需的权限。 若要使用 Microsoft Entra ID 进行授权(建议),需要 Azure RBAC 内置角色“存储 Blob 数据参与者”或更高级别的角色

关于数据移动库

Azure 存储数据移动库由通用客户端库和适用于 Azure Blob 存储和 Azure 文件的扩展库组成。 通用库提供传输数据的核心功能,而扩展库则提供特定于 Blob 存储和 Azure 文件的功能。 若要了解更多信息,请参阅下列资源:

创建 TransferManager 对象

TransferManager 是启动和控制所有类型传输(包括上传、下载和复制)的主要类。 在本节中,你将了解如何创建一个 TransferManager 对象,以便与本地文件系统、Blob 存储或 Azure 文件配合使用。

注意

管理 Azure SDK 客户端的最佳做法是将客户端视为单一实例,这意味着一个类一次只有一个对象。 无需为一组给定的构造函数参数或客户端选项保留多个客户端实例。

以下代码演示如何创建 TransferManager 对象:

TransferManager transferManager = new(new TransferManagerOptions());

可以选择向构造函数提供 TransferManagerOptions 的实例,这会将某些配置选项应用于由 TransferManager 对象启动的所有传输。 以下是可用的配置选项:

  • CheckpointStoreOptions:可选。 定义用于创建保存传输状态的检查点的选项,以便恢复传输。
  • Diagnostics:获取传输管理器诊断选项。
  • ErrorHandling:可选。 定义在传输过程中如何处理错误。 默认值为 StopOnAnyFailure
  • MaximumConcurrency:并行传输中可使用的最大工作线程数。
  • ProvidersForResuming:传输管理器在恢复传输时使用的资源提供程序。 预计每个正在使用的存储提供程序都有一个相应的提供程序。 若要了解详细信息,请参阅恢复现有传输

创建 StorageResource 对象

StorageResource 是所有存储资源(包括 Blob 和文件)的基类。 若要创建 StorageResource 对象,请使用以下提供程序类之一:

为 Blob 存储创建 StorageResource 对象

以下代码演示如何使用 Uri 为 blob 容器和 blob 创建 StorageResource 对象:

// Create a token credential
TokenCredential tokenCredential = new DefaultAzureCredential();

BlobsStorageResourceProvider blobsProvider = new(tokenCredential);

// Get a container resource
StorageResource container = await blobsProvider.FromContainerAsync(
    new Uri("http://<storage-account-name>.blob.core.windows.net/sample-container"));

// Get a block blob resource - default is block blob
StorageResource blockBlob = await blobsProvider.FromBlobAsync(
    new Uri("http://<storage-account-name>.blob.core.windows.net/sample-container/sample-block-blob"),
    new BlockBlobStorageResourceOptions());

// Use a similar approach to get a page blob or append blob resource

也可以使用 Azure.Storage.Blobs 中的客户端对象创建 StorageResource 对象。

// Create a token credential
TokenCredential tokenCredential = new DefaultAzureCredential();

BlobContainerClient blobContainerClient = new(
    new Uri("https://<storage-account-name>.blob.core.windows.net/sample-container"),
    tokenCredential);
StorageResource containerResource = BlobsStorageResourceProvider.FromClient(blobContainerClient);

BlockBlobClient blockBlobClient = blobContainerClient.GetBlockBlobClient("sample-block-blob");
StorageResource blockBlobResource = BlobsStorageResourceProvider.FromClient(blockBlobClient);

// Use a similar approach to get a page blob or append blob resource

启动新传输

所有传输都需要指定源和目标。 源和目标的类型均为 StorageResource,可以是 StorageResourceContainerStorageResourceItem。 对于给定的传输,源和目标必须属于同一类型。 例如,如果源是一个 blob 容器,目标也必须是一个 blob 容器。

可以通过调用以下方法启动新传输:

此方法会返回一个表示该传输的 TransferOperation 对象。 可以使用 TransferOperation 对象监控传输进度或获取传输 ID。 传输 ID 是传输的唯一标识符,需要该标识符来恢复传输或暂停传输。

可以选择向 StartTransferAsyncResumeTransferAsync 提供 TransferOptions 的实例,这会将某些配置选项应用于特定传输。 以下是可用的配置选项:

  • CreationMode:配置传输遇到已存在的资源时的行为。 启动新传输时默认为 FailIfExists。 恢复传输时,默认值可能会有所不同。 对于传输开始时成功枚举的所有资源,CreationMode 默认为最初使用的值。 对于任何其余资源,将应用常规默认值。
  • InitialTransferSize:第一个范围请求的大小(以字节为单位)。 单个传输大小小于此限制时,将通过单个请求上传或下载。 大于此限制的传输将继续以 MaximumTransferChunkSize 大小的区块进行下载或上传。 默认值为 32 MiB。 恢复传输时,默认值为首次启动传输时指定的值。
  • MaximumTransferChunkSize:分块传输数据时每个区块使用的最大大小。 默认值为 4 MiB。 恢复传输时,默认值为首次启动传输时指定的值。
  • ProgressHandlerOptions:可选。 用于更改 ProgressHandler 行为的选项。

示例:将本地目录上传到 blob 容器

以下代码示例演示如何启动新传输,以将本地目录上传到 blob 容器:

// Create a token credential
TokenCredential tokenCredential = new DefaultAzureCredential();

TransferManager transferManager = new(new TransferManagerOptions());

BlobsStorageResourceProvider blobsProvider = new(tokenCredential);

string localDirectoryPath = "C:/path/to/directory";
Uri blobContainerUri = new Uri("https://<storage-account-name>.blob.core.windows.net/sample-container");

TransferOperation transferOperation = await transferManager.StartTransferAsync(
    sourceResource: LocalFilesStorageResourceProvider.FromDirectory(localDirectoryPath),
    destinationResource: await blobsProvider.FromContainerAsync(blobContainerUri));
await transferOperation.WaitForCompletionAsync();

示例:复制容器或 blob

可以使用数据移动库在两个 StorageResource 实例之间进行复制。 对于 blob 资源,传输将使用从 URL 放置 Blob 操作,这会执行服务器到服务器的复制。

以下代码示例演示如何启动新传输,以将源 blob 容器中的所有 blob 复制到目标 blob 容器。 目标容器必须已经存在。 在此示例中,我们将 CreationMode 设置为 OverwriteIfExists,以覆盖任何已存在的目标 blob。 可以根据应用的需求调整 CreationMode 属性。

Uri sourceContainerUri = new Uri("https://<storage-account-name>.blob.core.windows.net/source-container");
Uri destinationContainerUri = new Uri("https://<storage-account-name>.blob.core.windows.net/dest-container");

TransferOperation transferOperation = await transferManager.StartTransferAsync(
    sourceResource: await blobsProvider.FromContainerAsync(
        sourceContainerUri,
        new BlobStorageResourceContainerOptions()
        {
            BlobPrefix = "source/directory/prefix"
        }),
    destinationResource: await blobsProvider.FromContainerAsync(
        destinationContainerUri,
        new BlobStorageResourceContainerOptions()
        {
            // All source blobs are copied as a single type of destination blob
            // Defaults to block blob, if not specified
            BlobType = BlobType.Block,
            BlobPrefix = "destination/directory/prefix"
        }),
    transferOptions: new TransferOptions()
    {
        CreationMode = StorageResourceCreationMode.OverwriteIfExists,
    }
);
await transferOperation.WaitForCompletionAsync();

以下代码示例演示如何启动新传输,以将源 blob 复制到目标 blob。 在此示例中,我们将 CreationMode 设置为 OverwriteIfExists,以覆盖任何已存在的目标 blob。 可以根据应用的需求调整 CreationMode 属性。

Uri sourceBlobUri = new Uri(
    "https://<storage-account-name>.blob.core.windows.net/source-container/source-blob");
Uri destinationBlobUri = new Uri(
    "https://<storage-account-name>.blob.core.windows.net/dest-container/dest-blob");

TransferOperation transferOperation = await transferManager.StartTransferAsync(
    sourceResource: await blobsProvider.FromBlobAsync(sourceBlobUri),
    destinationResource: await blobsProvider.FromBlobAsync(destinationBlobUri, new BlockBlobStorageResourceOptions()),
    transferOptions: new TransferOptions()
    {
        CreationMode = StorageResourceCreationMode.OverwriteIfExists,
    }
);
await transferOperation.WaitForCompletionAsync();

恢复现有传输

通过将传输进度持久保存到磁盘,数据移动库能够恢复在完成前失败或以其他方式取消或暂停的传输。 若要恢复传输,必须为 TransferManager 对象配置 StorageResourceProvider 实例,这些实例能够从持久化数据中重组传输。 可以使用 TransferManagerOptions 类的 ProvidersForResuming 属性来指定提供程序。

以下代码示例演示如何初始化一个能够在本地文件系统和 Blob 存储之间恢复传输的 TransferManager 对象:

// Create a token credential
TokenCredential tokenCredential = new DefaultAzureCredential();

TransferManager transferManager = new(new TransferManagerOptions()
{
    ProvidersForResuming = new List<StorageResourceProvider>()
    {
        new BlobsStorageResourceProvider(tokenCredential)
    }
});

若要恢复传输,请调用以下方法:

提供要恢复的传输的传输 ID。 传输 ID 是传输的唯一标识符,在传输启动时作为 TransferOperation 对象的一部分返回。 如果不知道传输 ID 的值,可以调用 TransferManager.GetTransfersAsync 查找传输及其对应的 ID。

以下代码示例演示如何恢复传输:

TransferOperation resumedTransfer = await transferManager.ResumeTransferAsync(transferId: ID);

注意

如果 TransferCheckpointStoreOptions 作为 TransferManagerOptions 的一部分进行设置,则持久化传输数据的位置与默认位置不同。 若要恢复使用自定义检查点存储记录的传输,必须为恢复传输的 TransferManager 对象提供相同的检查点存储选项。

监视传输进度

根据应用的需求,可以通过多种机制监视和观察传输。 在本节中,你将了解如何使用 TransferOperation 对象监视传输进度,以及如何使用 TransferOptions 事件监视传输。

示例:使用 TransferOperation 对象监视传输进度

可以使用 StartTransferAsync 方法返回的 TransferOperation 对象监视传输进度。 还可以调用 TransferManager.GetTransfersAsync 来枚举 TransferManager 对象的所有传输。

以下代码示例演示如何循环访问所有传输,并将每个传输的状态写入日志文件:

async Task CheckTransfersAsync(TransferManager transferManager)
{
    await foreach (TransferOperation transfer in transferManager.GetTransfersAsync())
    {
        using StreamWriter logStream = File.AppendText("path/to/log/file");
        logStream.WriteLine(Enum.GetName(typeof(TransferState), transfer.Status.State));
    }
}

TransferStatus 定义传输作业的状态。 TransferStatus 包含以下属性:

properties 类型​​ 说明
HasCompletedSuccessfully Boolean 表示传输是否成功完成,没有任何失败或跳过的项。
HasFailedItems 布尔 表示传输是否有任何失败项。 如果设置为 true,则传输有至少一个失败项。 如果设置为 false,则传输当前没有失败项。
HasSkippedItems 布尔 表示传输是否有任何跳过的项。 如果设置为 true,则传输有至少一个跳过的项。 如果设置为 false,则传输当前没有跳过的项。 如果在 TransferOptions.CreationMode 中未启用 SkipIfExists,则有可能永远不会跳过任何项。
State TransferState 定义传输可能具有的状态类型。 有关详细信息,请参阅 TransferState

示例:使用 TransferOptions 事件监视传输进度

可以通过侦听 TransferOptions 类提供的事件来监视传输进度。 系统将 TransferOptions 实例传递至 StartTransferAsync 方法,并提供事件,这些事件在传输完成、失败、跳过或状态更改时触发。

以下代码示例演示如何使用 TransferOptions 侦听传输完成事件:

async Task<TransferOperation> ListenToTransfersAsync(
    TransferManager transferManager,
    StorageResource source,
    StorageResource destination)
{
    TransferOptions transferOptions = new();
    transferOptions.ItemTransferCompleted += (TransferItemCompletedEventArgs args) =>
    {
        using (StreamWriter logStream = File.AppendText("path/to/log/file"))
        {
            logStream.WriteLine($"File Completed Transfer: {args.Source.Uri.AbsoluteUri}");
        }
        return Task.CompletedTask;
    };
    return await transferManager.StartTransferAsync(
        source,
        destination,
        transferOptions);
}

BlobContainerClient 使用扩展方法

对于已有代码使用 Azure.Storage.Blobs 中的 BlobContainerClient 类的应用程序,可以使用扩展方法直接从 BlobContainerClient 对象启动传输。 该扩展方法在 BlobContainerClientExtensions 类(对于 Azure 文件为 ShareDirectoryClientExtensions)中提供,并且能在对代码改动最小的情况下提供使用 TransferManager 的一些优势。 在本节中,你将了解如何使用扩展方法从 BlobContainerClient 对象执行传输。

安装 Azure.Storage.Blobs 包(如果尚未安装):

dotnet add package Azure.Storage.Blobs

在代码文件顶部添加以下 using 指令:

using Azure.Storage.Blobs;
using Azure.Storage.Blobs.Models;

以下代码示例演示如何为名为 sample-container 的 blob 容器实例化 BlobContainerClient

// Create a token credential
TokenCredential tokenCredential = new DefaultAzureCredential();

BlobServiceClient client = new BlobServiceClient(
    new Uri("https://<storage-account-name>.blob.core.windows.net"),
    tokenCredential);

BlobContainerClient containerClient = client.GetBlobContainerClient("sample-container");

以下代码示例演示如何使用 UploadDirectoryAsync 将本地目录内容上传到 sample-container

TransferOperation transfer = await containerClient
    .UploadDirectoryAsync(WaitUntil.Started, "local/directory/path");

await transfer.WaitForCompletionAsync();

以下代码示例展示了如何使用 DownloadToDirectoryAsyncsample-container 的内容下载到本地目录:

TransferOperation transfer = await containerClient
    .DownloadToDirectoryAsync(WaitUntil.Started, "local/directory/path");

await transfer.WaitForCompletionAsync();

若要详细了解 BlobContainerClient 的扩展方法,请参阅 BlobContainerClient 上的扩展

下一步