将一个Azure Blob复制到Azure Storage Client 2.0中的另一个Blob

时间:2013-01-04 06:17:12

标签: c# azure azure-storage

在旧的1.7存储客户端中有一个CloudBlob.CopyFromBlob(otherBlob)方法,但它似乎不存在于2.0版本中。复制blob的建议最佳做法是什么?我确实看到了ICloudBlob.BeginStartCopyFromBlob方法。如果这是合适的方法,我该如何使用它?

8 个答案:

答案 0 :(得分:52)

Gaurav Mantri在2.0版本上编写了一系列关于Azure存储的文章。我从他的Storage Client Library 2.0 – Migrating Blob Storage Code博客文章中获取了Blob Copy

的代码摘录
CloudStorageAccount storageAccount = new CloudStorageAccount(new StorageCredentials(accountName, accountKey), true);
CloudBlobClient cloudBlobClient = storageAccount.CreateCloudBlobClient();
CloudBlobContainer sourceContainer = cloudBlobClient.GetContainerReference(containerName);
CloudBlobContainer targetContainer = cloudBlobClient.GetContainerReference(targetContainerName);
string blobName = "<Blob Name e.g. myblob.txt>";
CloudBlockBlob sourceBlob = sourceContainer.GetBlockBlobReference(blobName);
CloudBlockBlob targetBlob = targetContainer.GetBlockBlobReference(blobName);
targetBlob.StartCopyFromBlob(sourceBlob);

答案 1 :(得分:30)

使用Storage 6.3(比原始问题更新的库)和异步方法使用StartCopyAsync(MSDN

  CloudStorageAccount storageAccount = CloudStorageAccount.Parse("Your Connection");

  CloudBlobClient blobClient = storageAccount.CreateCloudBlobClient();
  CloudBlobContainer container = blobClient.GetContainerReference("YourContainer");

  CloudBlockBlob source = container.GetBlockBlobReference("Your Blob");
  CloudBlockBlob target = container.GetBlockBlobReference("Your New Blob"");

  await target.StartCopyAsync(source);

答案 2 :(得分:14)

SDK的最新版本(7.x)开始,由于BeginStartCopyBlob功能不再存在,因此不再有效。

你可以这样做:

// this tunnels the data via your program,
// so it reuploads the blob instead of copying it on service side
using (var stream = await sourceBlob.OpenReadAsync())
{
  await destinationBlob.UploadFromStreamAsync(stream);
}
编辑:由Talon撰写

如@(Alexey Shcherbak)所述,这是一个更好的方法:

targetCloudBlob.StartCopy(sourceCloudBlob.Uri);
or
targetCloudBlob.StartCopyAsync(sourceCloudBlob.Uri);

while (targetCloudBlob.CopyState.Status == CopyStatus.Pending)
{
    Thread.Sleep(500);
}

if (targetCloudBlob.CopyState.Status != CopyStatus.Success)
{
    throw new Exception("Copy failed: " +    targetCloudBlob.CopyState.Status);
}

答案 3 :(得分:10)

Naveen已经解释了使用StartCopyFromBlob(同步方法)的正确语法。您提到的方法(BeginStartCopyFromBlob)是异步替代方法,您可以将其与Task结合使用,例如:

    var blobClient = account.CreateCloudBlobClient();

    // Upload picture.
    var picturesContainer = blobClient.GetContainerReference("pictures");
    picturesContainer.CreateIfNotExists();
    var myPictureBlob = picturesContainer.GetBlockBlobReference("me.png");
    using (var fs = new FileStream(@"C:\Users\Public\Pictures\Sample Pictures\Chrysanthemum.jpg", FileMode.Open))
        myPictureBlob.UploadFromStream(fs);

    // Backup picture.
    var backupContainer = blobClient.GetContainerReference("backup");
    backupContainer.CreateIfNotExists();
    var backupBlob = picturesContainer.GetBlockBlobReference("me.png");

    var task = Task.Factory.FromAsync<string>(backupBlob.BeginStartCopyFromBlob(myPictureBlob, null, null), backupBlob.EndStartCopyFromBlob);
    task.ContinueWith((t) =>
    {
        if (!t.IsFaulted)
        {
            while (true)
            {
                Console.WriteLine("Copy state for {0}: {1}", backupBlob.Uri, backupBlob.CopyState.Status);
                Thread.Sleep(500);
            }
        }
        else
        {
            Console.WriteLine("Error: " + t.Exception);
        }
    });

答案 4 :(得分:8)

对我来说,WindowsAzure.Storage 8.0.1,James Hancock的解决方案做了服务器端副本,但客户端副本状态卡在Pending上(永远循环)。解决方法是在FetchAttributes()之后在targetCloudBlob上致电Thread.sleep(500)

// Aaron Sherman's code 

targetCloudBlob.StartCopy(sourceCloudBlob.Uri);

while (targetCloudBlob.CopyState.Status == CopyStatus.Pending)
{
    Thread.Sleep(500);
    targetCloudBlob.FetchAttributes();
}

// James Hancock's remaining code

Official Microsoft documentation (async example)

答案 5 :(得分:8)

启动Azure存储8,在存储帐户之间移动Blob我使用类似于下面的代码,希望它可以帮助某人:

def declare_exchanges(self):
    exchange = "exchangeA"
    callback = self.on_exchange(exchange)
    channel.exchange_declare(callback=callback, exchange=exchange)

    exchange = "exchangeB"
    callback = self.on_exchange(exchange)
    channel.exchange_declare(callback=callback, exchange=exchange)

def on_exchange(self, exchange):
    def callback(response):
        print(exchange)

    return callback

答案 6 :(得分:2)

API 似乎自之前的帖子发布以来可能已经清理了一些。

// _client is a BlobServiceClient injected via DI in the constructor.

BlobContainerClient sourceContainerClient = _client.GetBlobContainerClient(sourceContainerName);
BlobClient sourceClient = sourceContainerClient.GetBlobClient(blobName);

BlobContainerClient destContainerClient = _client.GetBlobContainerClient(destContainerName);
BlobClient destClient = destContainerClient.GetBlobClient(blobName);

// assume that if the following doesn't throw an exception, then it is successful.
CopyFromUriOperation operation = await destClient.StartCopyFromUriAsync(sourceClient.Uri);
await operation.WaitForCompletionAsync();

operation.WaitForCompletionAsync 的文档说:

<块引用>

定期调用服务器直到长时间运行的操作完成。该方法会定期调用UpdateStatusAsync,直到HasCompleted为true,然后返回操作的最终结果。

查看此方法的源代码似乎会调用 BlobBaseClient.GetProperties(或异步版本),它会在出错时抛出 RequestFailureException

答案 7 :(得分:1)

这是我简短的简单回答。

public void Copy(CloudBlockBlob srcBlob, CloudBlobContainer destContainer)
{
    CloudBlockBlob destBlob;

    if (srcBlob == null)
    {
        throw new Exception("Source blob cannot be null.");
    }

    if (!destContainer.Exists())
    {
        throw new Exception("Destination container does not exist.");
    }

    //Copy source blob to destination container
    string name = srcBlob.Uri.Segments.Last();
    destBlob = destContainer.GetBlockBlobReference(name);
    destBlob.StartCopyAsync(srcBlob);                
}