Dans l'ancien client de stockage 1.7, il y avait une méthode CloudBlob.CopyFromBlob (otherBlob), mais elle ne semble pas être présente dans la version 2.0. Quelle est la meilleure pratique recommandée pour copier des objets blob? Je vois une méthode ICloudBlob.BeginStartCopyFromBlob. Si c'est la méthode appropriée, comment puis-je l'utiliser?
Gaurav Mantri a écrit une série d'articles sur Azure Storage sur la version 2.0. J'ai pris cet extrait de code de son article de blog Storage Client Library 2.0 - Migrating Blob Storage Code for 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);
L'utilisation de Storage 6.3 (bibliothèque beaucoup plus récente que dans la question d'origine) et les méthodes asynchrones utilisent 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);
Pour info depuis la dernière version (7.x) de SDK
cela ne fonctionne plus car la fonction BeginStartCopyBlob
n'existe plus.
Vous pouvez le faire de cette façon:
// 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);
}
Comme mentionné par @ (Alexey Shcherbak), c'est une meilleure façon de procéder:
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);
}
À partir d'Azure Storage 8, pour déplacer des objets blob entre les comptes de stockage, j'utilise un code similaire à celui ci-dessous, j'espère que cela aide quelqu'un:
//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.");
Naveen a déjà expliqué la syntaxe correcte pour utiliser StartCopyFromBlob
(la méthode synchrone). La méthode que vous avez mentionnée (BeginStartCopyFromBlob
) est l'alternative asynchrone que vous pouvez utiliser en combinaison avec un Task
par exemple:
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);
}
});
Pour moi, WindowsAzure.Storage 8.0.1, la solution de James Hancock a fait la copie côté serveur mais le statut de la copie client était bloqué sur Pending
(boucle pour toujours). La solution consistait à appeler FetchAttributes()
sur targetCloudBlob
après 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
voici ma courte réponse 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);
}