.NET を使用して非同期スケジュールを設定して BLOB をコピーする

この記事では、.NET 用の Azure Storage クライアント ライブラリを使用して非同期スケジュールを設定して BLOB をコピーする方法について説明します。 BLOB は、同じストレージ アカウント内のソースからでも、別のストレージ アカウント内のソースからでも、特定の URL に対する HTTP GET 要求を介して取得されたアクセス可能なオブジェクトからでもコピーできます。 保留中のコピー操作を中止することもできます。

この記事で説明するクライアント ライブラリ メソッドでは、Copy Blob REST API 操作が使用されます。また、このメソッドは、非同期スケジュールを設定してコピーを実行する場合に使用できます。 ストレージ アカウントにデータを移動し、ソース オブジェクトの URL がわかっているほとんどのコピー シナリオについては、「.NET を使用してソース オブジェクト URL から BLOB をコピーする」を参照してください。

前提条件

  • この記事では、.NET 用の Azure Blob Storage クライアント ライブラリを操作するようにプロジェクトが既に設定されていることを前提としています。 パッケージのインストール、using ディレクティブの追加、認可されたクライアント オブジェクトの作成など、プロジェクトの設定については、「Azure Blob Storage と .NET の作業を始める」を参照してください。
  • 認可メカニズムには、コピー操作を実行または保留中のコピーを中止するためのアクセス許可が必要です。 詳細については、次の REST API 操作の認可ガイダンスを参照してください。

非同期スケジュールを設定した BLOB のコピーについて

Copy Blob 操作は、非同期的に完了でき、ベスト エフォートで実行されます。つまり、即座に開始することも、指定の時間枠内に完了することも保証されていません。 コピー操作はバックグラウンドでスケジュールされ、サーバーに使用可能なリソースがある場合に実行されます。 コピーが同じストレージ アカウント内で行われる場合、操作は同期的に完了できます。

Copy Blob 操作では、次のいずれかのアクションを実行できます。

  • コピー元 BLOB を別の名前でコピー先 BLOB にコピーします。 コピー先 BLOB は、同じ BLOB の種類 (ブロック、アペンド、またはページ) の既存の BLOB でも、コピー操作によって作成される新しい BLOB でもかまいません。
  • ソース BLOB を同じ名前でコピー先 BLOB にコピーして、コピー先 BLOB を置き換えます。 この種のコピー操作では、コミットされていないブロックはすべて削除され、コピー先 BLOB のメタデータが上書きされます。
  • Azure File Service 内のコピー元ファイルをコピー先 BLOB にコピーします。 コピー先 BLOB は、既存のブロック BLOB でも、コピー操作によって作成される新しいブロック BLOB でもかまいません。 ファイルからページ BLOB またはアペンド BLOB へのコピーはサポートされていません。
  • スナップショットをベース BLOB にコピーします。 スナップショットをベース BLOB に昇格することにより、BLOB を以前のバージョンに復元できます。
  • スナップショットを別の名前でコピー先 BLOB にコピーします。 結果として得られるコピー先 BLOB は書き込み可能な BLOB であり、スナップショットではありません。

プロパティ、インデックス タグ、メタデータ、課金に関する情報など、Copy Blob 操作の詳細については、BLOB リマークのコピーに関するページを参照してください。

非同期スケジュールを設定して BLOB をコピーする

このセクションでは、非同期スケジュールを設定してコピー操作を実行するために、.NET 用の Azure Storage クライアント ライブラリによって提供されるメソッドの概要について説明します。

次のメソッドは、Copy Blob REST API 操作をラップし、ソース BLOB からのデータの非同期コピーを開始します。

StartCopyFromUri メソッドと StartCopyFromUriAsync メソッドは、コピー操作に関する情報が含まれる CopyFromUriOperation オブジェクトを返します。 これらのメソッドは、コピー操作の非同期スケジュールが必要な場合に使用できます。

Azure 内のソースから BLOB をコピーする

同じストレージ アカウント内の BLOB をコピーする場合、操作は同期的に完了できます。 ソース BLOB へのアクセスは、Microsoft Entra ID、Shared Access Signature (SAS)、またはアカウント キーを使用して承認できます。 変更可能な同期コピー操作については、「.NET を使用してソース オブジェクト URL から BLOB をコピーする」を参照してください。

コピー ソースが別のストレージ アカウント内の BLOB である場合、操作は非同期的に完了できます。 ソース BLOB は、パブリックであるか、SAS トークンを介して認可されている必要があります。 SAS トークンには Read ('r') アクセス許可を含める必要があります。 SAS トークンの詳細については、「Shared Access Signatures によるアクセスの委任」を参照してください。

次の例は、非同期スケジュールを使用して別のストレージ アカウントからソース BLOB をコピーするシナリオを示しています。 この例では、追加されたユーザー委任 SAS トークンを使用してソース BLOB URL を作成します。 この例では、クライアント ライブラリを使用して SAS トークンを生成する方法を示していますが、独自のトークンを指定することもできます。 この例では、コピー操作中にソース BLOB をリースして、別のクライアントから BLOB が変更されないようにする方法も示します。 Copy Blob 操作では、コピー操作の開始時にソース BLOB の ETag 値が保存されます。 コピー操作が完了する前に ETag 値が変更されると、操作は失敗します。

//-------------------------------------------------
// Copy a blob from a different storage account
//-------------------------------------------------
public static async Task CopyAcrossStorageAccountsAsync(
    BlobClient sourceBlob,
    BlockBlobClient destinationBlob)
{
    // Lease the source blob to prevent changes during the copy operation
    BlobLeaseClient sourceBlobLease = new(sourceBlob);

    // Create a Uri object with a SAS token appended - specify Read (r) permissions
    Uri sourceBlobSASURI = await GenerateUserDelegationSAS(sourceBlob);

    try
    {
        await sourceBlobLease.AcquireAsync(BlobLeaseClient.InfiniteLeaseDuration);

        // Start the copy operation and wait for it to complete
        CopyFromUriOperation copyOperation = await destinationBlob.StartCopyFromUriAsync(sourceBlobSASURI);
        await copyOperation.WaitForCompletionAsync();
    }
    catch (RequestFailedException ex)
    {
        // Handle the exception
    }
    finally
    {
        // Release the lease once the copy operation completes
        await sourceBlobLease.ReleaseAsync();
    }
}

async static Task<Uri> GenerateUserDelegationSAS(BlobClient sourceBlob)
{
    BlobServiceClient blobServiceClient =
        sourceBlob.GetParentBlobContainerClient().GetParentBlobServiceClient();

    // Get a user delegation key for the Blob service that's valid for 1 day
    UserDelegationKey userDelegationKey =
        await blobServiceClient.GetUserDelegationKeyAsync(DateTimeOffset.UtcNow,
                                                          DateTimeOffset.UtcNow.AddDays(1));

    // Create a SAS token that's also valid for 1 day
    BlobSasBuilder sasBuilder = new BlobSasBuilder()
    {
        BlobContainerName = sourceBlob.BlobContainerName,
        BlobName = sourceBlob.Name,
        Resource = "b",
        StartsOn = DateTimeOffset.UtcNow,
        ExpiresOn = DateTimeOffset.UtcNow.AddDays(1)
    };

    // Specify read permissions for the SAS
    sasBuilder.SetPermissions(BlobSasPermissions.Read);

    // Add the SAS token to the blob URI
    BlobUriBuilder blobUriBuilder = new BlobUriBuilder(sourceBlob.Uri)
    {
        // Specify the user delegation key
        Sas = sasBuilder.ToSasQueryParameters(userDelegationKey,
                                              blobServiceClient.AccountName)
    };

    return blobUriBuilder.ToUri();
}

Note

ユーザー委任 SAS トークンでは、アカウント キーではなく Microsoft Entra の資格情報で署名されているため、セキュリティが強化されます。 ユーザー委任 SAS トークンを作成するには、Microsoft Entra セキュリティ プリンシパルに適切なアクセス許可が必要です。 認可要件については、「ユーザー委任キーを取得する」を参照してください。

Azure 外部のソースから BLOB をコピーする

Azure 外部にあるアクセス可能なオブジェクトを含め、特定の URL に対する HTTP GET 要求を介して取得できる任意のソース オブジェクトにコピー操作を実行できます。 次の例は、アクセス可能なソース オブジェクト URL から BLOB をコピーするシナリオを示しています。

//-------------------------------------------------
// Copy a blob from an external source
//-------------------------------------------------
public static async Task CopyFromExternalSourceAsync(
    string sourceLocation,
    BlockBlobClient destinationBlob)
{
    Uri sourceUri = new(sourceLocation);

    // Start the copy operation and wait for it to complete
    CopyFromUriOperation copyOperation = await destinationBlob.StartCopyFromUriAsync(sourceUri);
    await copyOperation.WaitForCompletionAsync();
}

コピー操作の状態を確認する

Copy Blob 操作の状態を確認するには、UpdateStatusAsync を呼び出し、応答を解析して x-ms-copy-status ヘッダーの値を取得します。

次のコード例は、コピー操作の状態を確認する方法を示しています。

public static async Task CheckCopyStatusAsync(CopyFromUriOperation copyOperation)
{
    // Check for the latest status of the copy operation
    Response response = await copyOperation.UpdateStatusAsync();

    // Parse the response to find x-ms-copy-status header
    if (response.Headers.TryGetValue("x-ms-copy-status", out string value))
        Console.WriteLine($"Copy status: {value}");
}

コピー操作を中止する

保留中の Copy Blob 操作を中止すると、コピー先 BLOB の長さは 0 になります。 ただし、コピー先 BLOB のメタデータは、ソース BLOB からコピーされた値、またはコピー操作中に明示的に設定された値に変わります。 コピー前のメタデータを元のまま維持するには、いずれかのコピー方法を呼び出す前に、コピー先 BLOB のスナップショットを作成します。

保留中のコピー操作を中止するには、次のいずれかの操作を呼び出します。

これらのメソッドは、保留中の Copy Blob 操作を取り消す Abort Copy Blob REST API 操作をラップします。 次のコード例は、保留中の Copy Blob 操作を中止する方法を示しています。

public static async Task AbortBlobCopyAsync(
    CopyFromUriOperation copyOperation,
    BlobClient destinationBlob)
{
    // Check for the latest status of the copy operation
    Response response = await copyOperation.UpdateStatusAsync();

    // Parse the response to find x-ms-copy-status header
    if (response.Headers.TryGetValue("x-ms-copy-status", out string value))
    {
        if (value == "pending")
        {
            await destinationBlob.AbortCopyFromUriAsync(copyOperation.Id);
            Console.WriteLine($"Copy operation {copyOperation.Id} aborted");
        }
    }
}

リソース

.NET 用 Azure Blob Storage クライアント ライブラリを使用した BLOB のコピーについて詳しくは、次のリソースを参照してください。

REST API の操作

Azure SDK for .NET には Azure REST API に基づいて構築されたライブラリが含まれるため、使い慣れた .NET パラダイムを通じて REST API 操作を利用できます。 このアーティクルで説明するクライアント ライブラリ メソッドでは、次の REST API 操作を使用します:

コード サンプル

クライアント ライブラリのリソース