В старом клиентском хранилище 1.7 существовал метод CloudBlob.CopyFromBlob(otherBlob), но он, похоже, не присутствует в версии 2.0. Какова рекомендуемая передовая практика для копирования капли? Я вижу метод ICloudBlob.BeginStartCopyFromBlob. Если это подходящий метод, как его использовать?
Копирование одной лазурной бляшки на другой блок в Azure Storage Client 2.0
Ответ 1
Гаурав Мантри написал серию статей о хранилище Azure для версии 2.0. Я взял этот фрагмент кода из его блога Storage Client Library 2.0 - Миграция кода хранилища BLOB-объектов для BLOB-копии
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);
Ответ 2
Использование 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);
Ответ 3
К вашему сведению, с последней версии (7.x) SDK
это больше не работает, потому что функция 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);
}
Как отметил @(Алексей Щербак), это лучший способ продолжить:
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);
}
Ответ 4
Навин уже объяснил правильный синтаксис использования 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);
}
});
Ответ 5
Для меня, WindowsAzure.Storage 8.0.1, решение Джеймса Хэнкока сделало копию на стороне сервера, но состояние копии клиента зависло на Pending
(зацикливание навсегда). FetchAttributes()
было вызвать FetchAttributes()
для targetCloudBlob
после Thread.sleep(500)
.
// Aaron Sherman code
targetCloudBlob.StartCopy(sourceCloudBlob.Uri);
while (targetCloudBlob.CopyState.Status == CopyStatus.Pending)
{
Thread.Sleep(500);
targetCloudBlob.FetchAttributes();
}
// James Hancock remaining code
Ответ 6
Запуск Azure Storage 8 для перемещения Blobs между учетными записями хранилища Я использую код, похожий на ниже, надеюсь, что он поможет кому-то:
//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.");
Ответ 7
вот мой короткий простой ответ.
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);
}