Копирование большого двоичного объекта с помощью клиентских библиотек службы хранилища Azure

В этой статье показано, как скопировать большой двоичный объект в учетную запись хранения Azure. В нем также показано, как прервать асинхронную операцию копирования. В примере кода используются клиентские библиотеки службы хранилища Azure.

О копировании больших двоичных объектов

Копирование большого двоичного объекта в ту же учетную запись хранения — это синхронная операция. Копирование большого двоичного объекта между учетными записями — это асинхронная операция.

Исходный большой двоичный объект для операции копирования может быть блочным, добавочным, страничным либо представлять собой моментальный снимок. Если BLOB-объект назначения уже существует, он должен иметь тот же тип BLOB-объекта, что и BLOB-объект источника. Существующий целевой большой двоичный объект будет перезаписан.

Целевой большой двоичный объект невозможно изменить во время выполнения операции копирования. Большой двоичный объект может быть целью только одной невыполненной операции копирования. Иными словами, один большой двоичный объект невозможно назначить нескольким ожидающим операциям копирования.

Всегда копируется весь исходный большой двоичный объект или файл. Копирование диапазона байтов или набора блоков не поддерживается.

При копировании большого двоичного объекта в целевой большой двоичный объект назначения копируются приведенные ниже системные свойства с теми же значениями.

Операция копирования может принимать любую из следующих форм:

  • Копирование исходного большого двоичного объекта в целевой большой двоичный объект с другим именем. Целевым большим двоичным объектом может быть существующий большой двоичный объект того же типа (блочный или страничный) или новый большой двоичный объект, создаваемый операцией копирования.
  • Копирование исходного большого двоичного объекта в целевой большой двоичный объект с тем же именем, что фактически заменяет его. Такая операция копирования приводит к удалению всех незафиксированных блоков и перезаписи метаданных целевого большого двоичного объекта.
  • Копирование исходного файла из службы файлов Azure в целевой большой двоичный объект. Целевым большим двоичным объектом может быть существующий блочный BLOB-объект или новый блочный BLOB-объект, созданный операцией копирования. Копирование из файлов в страничные BLOB-объекты или добавочные BLOB-объекты не поддерживается.
  • Копирование моментального снимка поверх его базового большого двоичного объекта. Повысив уровень моментального снимка до базового большого двоичного объекта, можно восстановить более раннюю версию большого двоичного объекта.
  • Копирование моментального снимка в целевой большой двоичный объект с другим именем. Результирующий целевой большой двоичный объект не станет моментальным снимком, а будет большим двоичным объектом, доступным для записи.

Копирование BLOB-объекта

NET (пакет SDK версии 12).

Чтобы скопировать большой двоичный объект, вызовите один из следующих методов:

Методы StartCopyFromUri и StartCopyFromUriAsync возвращают объект CopyFromUriOperation, содержащий сведения об операции копирования.

Приведенный ниже пример кода возвращает объект BlobClient, представляющий собой созданный ранее большой двоичный объект, и копирует его в новый большой двоичный объект в том же контейнере:

private static async Task CopyBlobAsync(BlobContainerClient container)
{
    try
    {
        // Get the name of the first blob in the container to use as the source.
        string blobName = container.GetBlobs().FirstOrDefault().Name;

        // Create a BlobClient representing the source blob to copy.
        BlobClient sourceBlob = container.GetBlobClient(blobName);

        // Ensure that the source blob exists.
        if (await sourceBlob.ExistsAsync())
        {
            // Lease the source blob for the copy operation 
            // to prevent another client from modifying it.
            BlobLeaseClient lease = sourceBlob.GetBlobLeaseClient();

            // Specifying -1 for the lease interval creates an infinite lease.
            await lease.AcquireAsync(TimeSpan.FromSeconds(-1));

            // Get the source blob's properties and display the lease state.
            BlobProperties sourceProperties = await sourceBlob.GetPropertiesAsync();
            Console.WriteLine($"Lease state: {sourceProperties.LeaseState}");

            // Get a BlobClient representing the destination blob with a unique name.
            BlobClient destBlob = 
                container.GetBlobClient(Guid.NewGuid() + "-" + sourceBlob.Name);

            // Start the copy operation.
            await destBlob.StartCopyFromUriAsync(sourceBlob.Uri);

            // Get the destination blob's properties and display the copy status.
            BlobProperties destProperties = await destBlob.GetPropertiesAsync();

            Console.WriteLine($"Copy status: {destProperties.CopyStatus}");
            Console.WriteLine($"Copy progress: {destProperties.CopyProgress}");
            Console.WriteLine($"Completion time: {destProperties.CopyCompletedOn}");
            Console.WriteLine($"Total bytes: {destProperties.ContentLength}");

            // Update the source blob's properties.
            sourceProperties = await sourceBlob.GetPropertiesAsync();

            if (sourceProperties.LeaseState == LeaseState.Leased)
            {
                // Break the lease on the source blob.
                await lease.BreakAsync();

                // Update the source blob's properties to check the lease state.
                sourceProperties = await sourceBlob.GetPropertiesAsync();
                Console.WriteLine($"Lease state: {sourceProperties.LeaseState}");
            }
        }
    }
    catch (RequestFailedException ex)
    {
        Console.WriteLine(ex.Message);
        Console.ReadLine();
        throw;
    }
}

.NET (пакет SDK версии 11).

Чтобы скопировать большой двоичный объект, вызовите один из следующих методов:

Методы StartCopy и StartCopyAsync возвращают значение идентификатора копирования, которое используется для проверки состояния или отмены операции копирования.

Приведенный ниже пример кода возвращает ссылку на созданный ранее большой двоичный объект и копирует его в новый большой двоичный объект в том же контейнере:

private static async Task CopyBlockBlobAsync(CloudBlobContainer container)
{
    CloudBlockBlob sourceBlob = null;
    CloudBlockBlob destBlob = null;
    string leaseId = null;

    try
    {
        // Get a block blob from the container to use as the source.
        sourceBlob = container.ListBlobs().OfType<CloudBlockBlob>().FirstOrDefault();

        // Lease the source blob for the copy operation 
        // to prevent another client from modifying it.
        // Specifying null for the lease interval creates an infinite lease.
        leaseId = await sourceBlob.AcquireLeaseAsync(null);

        // Get a reference to a destination blob (in this case, a new blob).
        destBlob = container.GetBlockBlobReference("copy of " + sourceBlob.Name);

        // Ensure that the source blob exists.
        if (await sourceBlob.ExistsAsync())
        {
            // Get the ID of the copy operation.
            string copyId = await destBlob.StartCopyAsync(sourceBlob);

            // Fetch the destination blob's properties before checking the copy state.
            await destBlob.FetchAttributesAsync();

            Console.WriteLine("Status of copy operation: {0}", destBlob.CopyState.Status);
            Console.WriteLine("Completion time: {0}", destBlob.CopyState.CompletionTime);
            Console.WriteLine("Bytes copied: {0}", destBlob.CopyState.BytesCopied.ToString());
            Console.WriteLine("Total bytes: {0}", destBlob.CopyState.TotalBytes.ToString());
        }
    }
    catch (StorageException e)
    {
        Console.WriteLine(e.Message);
        Console.ReadLine();
        throw;
    }
    finally
    {
        // Break the lease on the source blob.
        if (sourceBlob != null)
        {
            await sourceBlob.FetchAttributesAsync();

            if (sourceBlob.Properties.LeaseState != LeaseState.Available)
            {
                await sourceBlob.BreakLeaseAsync(new TimeSpan(0));
            }
        }
    }
}

Чтобы скопировать большой двоичный объект, вызовите метод start_copy_from_url. Метод start_copy_from_url возвращает словарь, содержащий сведения об операции копирования.

Приведенный ниже пример кода возвращает объект BlobClient, представляющий собой созданный ранее большой двоичный объект, и копирует его в новый большой двоичный объект в том же контейнере:

def blob_copy(self, container_name, blob_name):

    # Create a BlobClient from a connection string
    # retrieved from an environment variable named
    # AZURE_STORAGE_CONNECTION_STRING.
    source_blob = BlobClient.from_connection_string(
        os.getenv("AZURE_STORAGE_CONNECTION_STRING"), 
        container_name, blob_name
        )

    try:
        # Lease the source blob for the copy operation
        # to prevent another client from modifying it.
        lease = BlobLeaseClient(source_blob)
        lease.acquire()

        # Get the source blob's properties and display the lease state.
        source_props = source_blob.get_blob_properties()
        print("Lease state: " + source_props.lease.state)

        # Create a BlobClient representing the
        # destination blob with a unique name.
        dest_blob = BlobClient.from_connection_string(
            os.getenv("AZURE_STORAGE_CONNECTION_STRING"),
            container_name, str(uuid.uuid4()) + "-" + blob_name
            )

        # Start the copy operation.
        dest_blob.start_copy_from_url(source_blob.url)

        # Get the destination blob's properties to check the copy status.
        properties = dest_blob.get_blob_properties()
        copy_props = properties.copy

        # Display the copy status.
        print("Copy status: " + copy_props["status"])
        print("Copy progress: " + copy_props["progress"])
        print("Completion time: " + str(copy_props["completion_time"]))
        print("Total bytes: " + str(properties.size))

        if (source_props.lease.state == "leased"):
            # Break the lease on the source blob.
            lease.break_lease()

            # Update the destination blob's properties to check the lease state.
            source_props = source_blob.get_blob_properties()
            print("Lease state: " + source_props.lease.state)

    except ResourceNotFoundError as ex:
        print("ResourceNotFoundError: ", ex.message)

    except ServiceRequestError as ex:
        print("ServiceRequestError: ", ex.message)

Прерывание операции копирования

Если прервать операцию копирования, то целевой большой двоичный объект будет нулевой длины. Однако в метаданные целевого большого двоичного объекта будут записаны новые значения, скопированные из исходного большого двоичного объекта либо заданные явно при вызове операции копирования. Чтобы сохранить исходные метаданные, существовавшие до копирования, создайте моментальный снимок целевого большого двоичного объекта перед вызовом методов копирования.

NET (пакет SDK версии 12).

Проверьте свойство BlobProperties.CopyStatus целевого большого двоичного объекта, чтобы получить состояние операции копирования. После завершения копирования конечный BLOB-объект будет зафиксирован.

При прерывании операции копирования большого двоичного объекта она переходит в состояниеCopyStatus.Aborted.

Методы AbortCopyFromUri и AbortCopyFromUriAsync позволяют отменить выполняемую операцию копирования.

// Get the destination blob's properties to check the copy status.
BlobProperties destProperties = destBlob.GetProperties();

// Check the copy status. If the status is pending, abort the copy operation.
if (destProperties.CopyStatus == CopyStatus.Pending)
{
    await destBlob.AbortCopyFromUriAsync(destProperties.CopyId);
    Console.WriteLine($"Copy operation {destProperties.CopyId} has been aborted.");
}

.NET (пакет SDK версии 11).

Проверьте свойство CopyState.Status целевого большого двоичного объекта, чтобы получить состояние операции копирования. После завершения копирования конечный BLOB-объект будет зафиксирован.

При прерывании операции копирования большого двоичного объекта она переходит в состояниеCopyStatus.Aborted.

Методы AbortCopy и AbortCopyAsync позволяют отменить выполняемую операцию копирования.

// Fetch the destination blob's properties before checking the copy state.
await destBlob.FetchAttributesAsync();

// Check the copy status. If it is still pending, abort the copy operation.
if (destBlob.CopyState.Status == CopyStatus.Pending)
{
    await destBlob.AbortCopyAsync(copyId);
    Console.WriteLine("Copy operation {0} has been aborted.", copyId);
}

Проверьте запись status в словаре CopyProperties, возвращенном методом get_blob_properties, чтобы получить состояние операции копирования. После завершения копирования конечный BLOB-объект будет зафиксирован.

При прерывании операции копирования записи status присваивается значение "aborted".

Метод abort_copy позволяет отменить выполняемую операцию копирования.

# Get the destination blob's properties to check the copy status.
properties = dest_blob.get_blob_properties()
copy_props = properties.copy

# Check the copy status. If the status is pending, abort the copy operation.
if (copy_props["status"] == "pending"):
    dest_blob.abort_copy(copy_props["id"])
    print("Copy operation " + copy_props["id"] + " has been aborted.")

Пакеты Azure SDK

Получите дополнительную информацию пакетах SDK для Azure:

Дальнейшие действия

Приведенные ниже разделы содержат сведения о копировании больших двоичных объектов и прерывании выполняемых операций копирования с помощью интерфейсов REST API Azure.