C# 将一个 Azure blob 复制到 Azure Storage Client 2.0 中的另一个 blob
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/14152087/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
Copying one Azure blob to another blob in Azure Storage Client 2.0
提问by Craig Smitham
In the old 1.7 storage client there was a CloudBlob.CopyFromBlob(otherBlob) method, but it does not seem to be present in the 2.0 version. What is the recommended best practice for copying blobs? I do see a ICloudBlob.BeginStartCopyFromBlob method. If that is the appropriate method, how do I use it?
在旧的 1.7 存储客户端中有一个 CloudBlob.CopyFromBlob(otherBlob) 方法,但它似乎没有出现在 2.0 版本中。复制 blob 的推荐最佳做法是什么?我确实看到了 iCloudBlob.BeginStartCopyFromBlob 方法。如果这是合适的方法,我该如何使用它?
采纳答案by Naveen Vijay
Gaurav Mantrihas written a series of articles on Azure Storage on version 2.0. I have taken this code extract from his blog post of Storage Client Library 2.0 – Migrating Blob Storage Codefor Blob Copy
Gaurav Mantri撰写了一系列关于 2.0 版 Azure 存储的文章。我从他的博客文章Storage Client Library 2.0 – Migrating Blob Storage Codefor 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);
回答by Sandrino Di Mattia
Naveen already explained the correct syntax for using StartCopyFromBlob
(the synchronous method). The method you mentioned (BeginStartCopyFromBlob
) is the asynchronous alternative which you can use in combination with a Task
for example:
Naveen 已经解释了使用StartCopyFromBlob
(同步方法)的正确语法。您提到的方法 ( BeginStartCopyFromBlob
) 是异步替代方法,您可以将其与 a 结合使用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);
}
});
回答by Aaron Sherman
Using Storage 6.3 (much newer library than in original question) and async methods use StartCopyAsync (MSDN)
使用 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);
回答by James Hancock
FYI as of the latest version (7.x) of the SDK
this no longer works because the BeginStartCopyBlob
function no longer exists.
仅供参考,从最新版本 (7.x) 开始,SDK
此BeginStartCopyBlob
功能不再有效,因为该功能不再存在。
You can do it this way:
你可以这样做:
// 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);
}
As mentioned by @(Alexey Shcherbak) this is a better way to proceed:
正如@(Alexey Shcherbak) 所提到的,这是一种更好的方法:
await targetCloudBlob.StartCopyAsync(sourceCloudBlob.Uri);
while (targetCloudBlob.CopyState.Status == CopyStatus.Pending)
{
await Task.Delay(500);
// Need to fetch or "CopyState" will never update
await targetCloudBlob.FetchAttributesAsync();
}
if (targetCloudBlob.CopyState.Status != CopyStatus.Success)
{
throw new Exception("Copy failed: " + targetCloudBlob.CopyState.Status);
}
回答by Darrelk
here is my short simple answer.
这是我简短的简单回答。
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);
}
回答by Vangaorth
For me, WindowsAzure.Storage 8.0.1, James Hancock's solution did the server side copy but the client copy status was stuck on Pending
(looping forever). Solution was to call FetchAttributes()
on targetCloudBlob
after Thread.sleep(500)
.
对我来说,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
回答by bladekp
Starting Azure Storage 8, to move Blobs between Storage Accounts I use code similar to below, hope it will help somebody:
启动 Azure Storage 8,在存储帐户之间移动 Blob 我使用类似于下面的代码,希望它会帮助某人:
//copy blobs - from
CloudStorageAccount sourceStorageAccount = new CloudStorageAccount(new StorageCredentials(storageFromName, storageFromKey), true);
CloudBlobClient sourceCloudBlobClient = sourceStorageAccount.CreateCloudBlobClient();
CloudBlobContainer sourceContainer = sourceCloudBlobClient.GetContainerReference(containerFromName);
//copy blobs - to
CloudStorageAccount targetStorageAccount = new CloudStorageAccount(new StorageCredentials(storageToName, storageToKey), true);
CloudBlobClient targetCloudBlobClient = targetStorageAccount.CreateCloudBlobClient();
CloudBlobContainer targetContainer = targetCloudBlobClient.GetContainerReference(containerToName);
//create target container if didn't exists
try{
await targetContainer.CreateIfNotExistsAsync();
}
catch(Exception e){
log.Error(e.Message);
}
CloudBlockBlob sourceBlob = sourceContainer.GetBlockBlobReference(blobName);
CloudBlockBlob targetBlob = targetContainer.GetBlockBlobReference(blobName);
try{
//initialize copying
await targetBlob.StartCopyAsync(sourceBlob.Uri);
}
catch(Exception ex){
log.Error(ex.Message);
//return error, in my case HTTP
return req.CreateResponse(HttpStatusCode.BadRequest, "Error, source BLOB probably has private access only: " +ex.Message);
}
//fetch current attributes
targetBlob.FetchAttributes();
//waiting for completion
while (targetBlob.CopyState.Status == CopyStatus.Pending){
log.Info("Status: " + targetBlob.CopyState.Status);
Thread.Sleep(500);
targetBlob.FetchAttributes();
}
//check status
if (targetBlob.CopyState.Status != CopyStatus.Success){
//return error, in my case HTTP
return req.CreateResponse(HttpStatusCode.BadRequest, "Copy failed with status: " + targetBlob.CopyState.Status);
}
//finally remove source in case Copy Status was Success
sourceBlob.Delete();
//and return success (in my case HTTP)
return req.CreateResponse(HttpStatusCode.OK, "Done.");