Copiar un blob de Azure a otro blob en Azure Storage Client 2.0

En el antiguo cliente de almacenamiento 1.7 había un método CloudBlob.CopyFromBlob (otherBlob), pero no parece estar presente en la versión 2.0. ¿Cuál es la mejor práctica recomendada para copiar blobs? Veo un método ICloudBlob.BeginStartCopyFromBlob. Si ese es el método apropiado, ¿cómo lo uso?

Gaurav Mantri ha escrito una serie de artículos sobre Azure Storage en la versión 2.0. He tomado este extracto del código de su blog de Storage Client Library 2.0 – Migración de Blob Storage Code para 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 = ""; CloudBlockBlob sourceBlob = sourceContainer.GetBlockBlobReference(blobName); CloudBlockBlob targetBlob = targetContainer.GetBlockBlobReference(blobName); targetBlob.StartCopyFromBlob(sourceBlob); 

Usando Storage 6.3 (una biblioteca mucho más nueva que en la pregunta original) y los métodos asíncronos usan 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); 

Para su información, a partir de la última versión (7.x) del SDK esto ya no funciona porque la función BeginStartCopyBlob ya no existe.

Puedes hacerlo de esta manera:

 // 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); } 

EDITAR: por Talon

Como lo menciona @ (Alexey Shcherbak) esta es una mejor manera de proceder:

 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); } 

Naveen ya explicó la syntax correcta para usar StartCopyFromBlob (el método síncrono). El método que mencionó ( BeginStartCopyFromBlob ) es la alternativa asíncrona que puede utilizar en combinación con una Task por ejemplo:

  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(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); } }); 

Para mí, WindowsAzure.Storage 8.0.1, la solución de James Hancock hizo la copia del lado del servidor, pero el estado de la copia del cliente quedó bloqueado ( Pending para siempre). La solución fue llamar a FetchAttributes() en targetCloudBlob después de 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 

Documentación oficial de Microsoft (ejemplo asíncrono)

Al iniciar Azure Storage 8, para mover Blobs entre cuentas de almacenamiento, uso un código similar al siguiente, espero que ayude a alguien:

 //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."); 

Aquí está mi breve respuesta simple.

 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); }