使用 Java 通过异步计划复制 Blob

本文介绍了如何使用适用于 Java 的 Azure 存储客户端库通过异步计划复制 Blob。 你可以从同一存储帐户中的源、不同存储帐户中的源或从通过 HTTP GET 请求在给定 URL 上检索的任何可访问对象复制 Blob。 还可以中止挂起的复制操作。

本文中介绍的客户端库方法将使用 Copy Blob REST API 操作,并且可以在想要基于异步计划执行复制时使用。 对于要将数据移动到存储帐户且具有源对象 URL 的大多数复制方案,请参阅使用 Java 从源对象 URL 复制 Blob

先决条件

设置你的环境

如果没有现有项目,请查看本部分,其中介绍了如何设置项目来使用适用于 Java 的 Azure Blob 存储客户端库。 有关详细信息,请参阅 Azure Blob 存储和 Java 入门

要使用本文中的代码示例,请按照以下步骤设置项目。

注意

本文使用 Maven 生成工具来生成和运行示例代码。 其他生成工具(例如 Gradle)也可与 Azure SDK for Java 一起使用。

安装包

在文本编辑器中打开 pom.xml 文件。 通过包括 BOM 文件包括直接依赖项来安装包。

添加 import 语句

添加以下 import 语句:

import com.azure.core.util.polling.*;
import com.azure.storage.blob.*;
import com.azure.storage.blob.models.*;
import com.azure.storage.blob.options.*;
import com.azure.storage.blob.sas.BlobSasPermission;
import com.azure.storage.blob.sas.BlobServiceSasSignatureValues;
import com.azure.storage.blob.specialized.*;

import java.time.*;
import java.util.*;

授权

授权机制必须具有执行复制操作或中止挂起的复制的必要权限。 对于使用 Microsoft Entra ID的授权(建议),最小特权 Azure RBAC 内置角色因多种因素而异。 若要了解详细信息,请参阅复制 Blob (REST API)中止复制 Blob (REST API) 的授权指导。

创建客户端对象

若要将应用连接到 Blob 存储,请创建 BlobServiceClient 的实例。

以下示例使用 BlobServiceClientBuilder 生成一个使用 DefaultAzureCredentialBlobServiceClient 对象,并演示如何创建容器和 Blob 客户端(如果需要):

// Azure SDK client builders accept the credential as a parameter
// TODO: Replace <storage-account-name> with your actual storage account name
BlobServiceClient blobServiceClient = new BlobServiceClientBuilder()
        .endpoint("https://<storage-account-name>.blob.core.chinacloudapi.cn/")
        .credential(new DefaultAzureCredentialBuilder().build())
        .buildClient();

// If needed, you can create a BlobContainerClient object from the BlobServiceClient
BlobContainerClient containerClient = blobServiceClient
        .getBlobContainerClient("<container-name>");

// If needed, you can create a BlobClient object from the BlobContainerClient
BlobClient blobClient = containerClient
        .getBlobClient("<blob-name>");

要详细了解如何创建和管理客户端对象,请参阅 创建和管理与数据资源交互的客户端对象

关于基于异步计划复制 Blob

Copy Blob 操作可以异步完成,并且是在尽最大努力的基础上执行的,这意味着该操作不一定会立即开始或在指定的时间范围内完成。 复制操作是在后台安排的,并在服务器具有可用资源时执行。 如果复制发生在同一存储帐户内,则操作可以同步完成。

Copy Blob 操作可以执行以下任何操作:

  • 将源 Blob 复制到具有不同名称的目标 Blob。 目标 Blob 可以是相同类型(块、追加或页类型)的现有 Blob,也可以是复制操作创建的新 Blob。
  • 将源 Blob 复制到具有相同名称的目标 Blob,从而替换目标 Blob。 此类复制操作会移除所有未提交的块,并覆盖目标 Blob 的元数据。
  • 将 Azure 文件服务中的源文件复制到目标 Blob。 目标 Blob 可以是现有的块 Blob,也可以是复制操作创建的新块 Blob。 不支持从文件复制到页 Blob 或追加 Blob。
  • 将快照复制到其基本 Blob 上。 通过将快照提升到基本 Blob 的位置,可还原早期版本的 Blob。
  • 将快照复制到具有不同名称的目标 Blob。 生成的目标 Blob 是可写的 Blob,而不是快照。

若要详细了解 Copy Blob 操作,包括有关属性、索引标记、元数据和计费的信息,请参阅 Copy Blob 注解

基于异步计划复制 Blob

本部分概述了由适用于 Java 的 Azure 存储客户端库提供的通过异步计划执行复制操作的方法。

以下方法可包装 复制 Blob REST API 操作,并开始从源 Blob 异步复制数据:

方法 beginCopy 会返回 SyncPoller 以轮询复制操作的进度。 轮询响应类型为 BlobCopyInfo。 如果需要为复制操作提供异步计划,则可以使用 beginCopy 方法。

在 Azure 中从源复制 blob

如果要在同一存储帐户中复制 Blob,操作可以同步完成。 可以通过 Microsoft Entra ID、共享访问签名 (SAS) 或帐户密钥来授权对源 Blob 的访问。 有关引起改变的同步复制操作,请参阅使用 Java 从源对象 URL 复制 Blob

如果复制源是其他存储帐户中的 Blob,则操作可以异步完成。 源 Blob 必须是公共的或通过 SAS 令牌获得授权。 SAS 令牌需要包含读取 ('r') 权限。 若要详细了解 SAS 令牌,请参阅使用共享访问签名委派权限

以下示例演示使用异步计划从其他存储帐户复制源 Blob 的方案。 在此示例中,我们将使用追加的用户委派 SAS 令牌创建源 Blob URL。 此示例演示了如何使用客户端库生成 SAS 令牌,但你也可以提供自己的令牌。 此示例还演示了如何在复制操作期间租用源 Blob,以防止有人从其他客户端对该 Blob 进行更改。 Copy Blob 操作会在复制操作开始时保存源 Blob 的 ETag 值。 如果 ETag 值在复制操作完成之前发生了更改,则操作将失败。

public void copyBlobAcrossStorageAccounts(BlobClient sourceBlob, BlockBlobClient destinationBlob) {
    // Lease the source blob during copy to prevent other clients from modifying it
    BlobLeaseClient lease = new BlobLeaseClientBuilder()
            .blobClient(sourceBlob)
            .buildClient();

    // Create a SAS token for the source blob or use an existing one
    String sasToken = generateUserDelegationSAS(
            sourceBlob.getContainerClient().getServiceClient(),
            sourceBlob);

    // Get the source blob URL and append the SAS token
    String sourceBlobSasURL = sourceBlob.getBlobUrl() + "?" + sasToken;

    try {
        // Specifying -1 creates an infinite lease
        lease.acquireLease(-1);

        // Start the copy operation and wait for it to complete
        final SyncPoller<BlobCopyInfo, Void> poller = destinationBlob.beginCopy(
                sourceBlobSasURL,
                Duration.ofSeconds(2));
        PollResponse<BlobCopyInfo> response = poller.waitUntil(LongRunningOperationStatus.SUCCESSFULLY_COMPLETED);
    } finally {
        // Release the lease once the copy operation completes
        lease.releaseLease();
    }
}

public String generateUserDelegationSAS(BlobServiceClient blobServiceClient, BlobClient sourceBlob) {
    // Get a user delegation key
    OffsetDateTime delegationKeyStartTime = OffsetDateTime.now();
    OffsetDateTime delegationKeyExpiryTime = OffsetDateTime.now().plusDays(1);
    UserDelegationKey key = blobServiceClient.getUserDelegationKey(
        delegationKeyStartTime,
        delegationKeyExpiryTime);

    // Create a SAS token that's valid for one day, as an example
    OffsetDateTime expiryTime = OffsetDateTime.now().plusDays(1);

    // Set the Read (r) permission on the SAS token
    BlobSasPermission permission = new BlobSasPermission().setReadPermission(true);

    BlobServiceSasSignatureValues sasValues = new BlobServiceSasSignatureValues(expiryTime, permission)
            .setStartTime(OffsetDateTime.now());

    // Create a SAS token that's valid for one day
    String sasToken = sourceBlob.generateUserDelegationSas(sasValues, key);

    return sasToken;
}

注意

用户委派 SAS 令牌提供了更高的安全性,因为它们是使用 Microsoft Entra 凭据而不是帐户密钥进行签名的。 若要创建用户委托 SAS 令牌,Microsoft Entra 安全主体需要适当的权限。 有关授权要求,请参阅获取用户委派密钥

从 Azure 外部的源复制 Blob

你可以对可通过 HTTP GET 请求在给定 URL 上检索的任何源对象执行复制操作,包括 Azure 外部的可访问对象。 以下示例演示了从可访问的源对象 URL 复制 Blob 的方案。

public void copyFromExternalSourceAsyncScheduling(String sourceURL, BlockBlobClient destinationBlob) {
    // Start the copy operation and wait for it to complete
    final SyncPoller<BlobCopyInfo, Void> poller = destinationBlob.beginCopy(
            sourceURL,
            Duration.ofSeconds(2));
    PollResponse<BlobCopyInfo> response = poller.waitUntil(LongRunningOperationStatus.SUCCESSFULLY_COMPLETED);
}

检查复制操作的状态

要检查 Copy Blob 操作的状态,可以对 SyncPoller 返回的 BlobCopyInfo 调用 getCopyStatus

以下代码示例演示了如何检查复制操作的状态:

public void checkCopyStatus(BlobCopyInfo copyInfo) {
    // Check the status of the copy operation 
    System.out.printf("Copy status", copyInfo.getCopyStatus());
}

中止复制操作

中止挂起的 Copy Blob 操作会导致目标 Blob 长度为零。 但是,目标 Blob 的元数据将包含从源 Blob 复制的新值,或者在复制操作过程中显式设置的新值。 若要在复制之前保留原始元数据,请在调用一个复制方法之前创建目标 Blob 的快照。

要中止挂起的复制操作,请调用以下方法之一:

此方法会包装中止复制 Blob REST API 操作,这会取消挂起的 Copy Blob 操作。 以下代码示例演示了如何中止挂起的 Copy Blob 操作:

public void abortCopy(BlobCopyInfo copyInfo, BlobClient destinationBlob) {
    // Check the copy status and abort if pending
    if (copyInfo.getCopyStatus() == CopyStatusType.PENDING) {
        destinationBlob.abortCopyFromUrl(copyInfo.getCopyId());
        System.out.printf("Copy operation %s has been aborted%n", copyInfo.getCopyId());
    }
}

资源

若要详细了解如何使用适用于 Java 的 Azure Blob 存储客户端库来复制 blob,请参阅以下资源。

代码示例

REST API 操作

Azure SDK for Java 包含基于 Azure REST API 而生成的库,允许你通过熟悉的 Java 范例与 REST API 操作进行交互。 本文中介绍的客户端库方法使用以下 REST API 操作:

客户端库资源

  • 本文是适用于 Java 的 Blob 存储开发人员指南的一部分。 若要了解详细信息,请参阅生成 Java 应用中的开发人员指南文章的完整列表。