62 votes

Renommer un Blob de stockage Azure

Est-il possible de renommer un Blob de stockage Azure en utilisant l'API de stockage Azure à partir d'un rôle Web ? La seule solution que j'ai pour le moment est de copier le blob vers un nouveau blob portant le bon nom et de supprimer l'ancien.

0 votes

Maintenant, oui en utilisant ADLS Gen 2 avec l'espace de nom hiérarchique - docs.microsoft.com/fr/us/azure/storage/data-lake-storage/

49voto

Zidad Points 3756

UPDATE :

J'ai mis à jour le code après les commentaires de @IsaacAbrahams et la réponse de @Viggity, cette version devrait vous éviter de devoir tout charger dans un MemoryStream, et attend que la copie soit terminée avant de supprimer le blob source.


Pour tous ceux qui arrivent en retard à la fête et qui tombent sur ce billet en utilisant l'API de stockage Azure V2, voici une version de l'API de stockage Azure. pour le faire rapidement et proprement (+ version asynchrone) :

public static class BlobContainerExtensions 
{
   public static void Rename(this CloudBlobContainer container, string oldName, string newName)
   {
      //Warning: this Wait() is bad practice and can cause deadlock issues when used from ASP.NET applications
      RenameAsync(container, oldName, newName).Wait();
   }

   public static async Task RenameAsync(this CloudBlobContainer container, string oldName, string newName)
   {
      var source = await container.GetBlobReferenceFromServerAsync(oldName);
      var target = container.GetBlockBlobReference(newName);

      await target.StartCopyFromBlobAsync(source.Uri);

      while (target.CopyState.Status == CopyStatus.Pending)
            await Task.Delay(100);

      if (target.CopyState.Status != CopyStatus.Success)
          throw new Exception("Rename failed: " + target.CopyState.Status);

      await source.DeleteAsync();
    }
}

Mise à jour pour Azure Storage 7.0

    public static async Task RenameAsync(this CloudBlobContainer container, string oldName, string newName)
    {
        CloudBlockBlob source =(CloudBlockBlob)await container.GetBlobReferenceFromServerAsync(oldName);
        CloudBlockBlob target = container.GetBlockBlobReference(newName);

        await target.StartCopyAsync(source);

        while (target.CopyState.Status == CopyStatus.Pending)
            await Task.Delay(100);

        if (target.CopyState.Status != CopyStatus.Success)
            throw new Exception("Rename failed: " + target.CopyState.Status);

        await source.DeleteAsync();            
    }

Avertissement : Il s'agit d'une méthode rapide et sale pour que le renommage s'exécute de manière synchrone. Cela correspond à mes besoins, mais comme d'autres utilisateurs l'ont noté, la copie peut prendre beaucoup de temps (jusqu'à plusieurs jours), donc la meilleure façon de procéder n'est PAS d'exécuter cette méthode en une seule fois comme cette réponse mais plutôt :

  • Démarrer le processus de copie
  • Interroger l'état de l'opération de copie
  • Supprimez le blob original lorsque la copie est terminée.

36voto

Rinat Abdullin Points 13520

Il y a moyen pratique de le faire bien qu'Azure API de service Blob ne prend pas directement en charge la possibilité de renommer ou de déplacer les blobs.

0 votes

Essayez l'API ADLS Gen 2 où vous pouvez renommer un blob comme vous renommez un fichier dans une opération atomique. - azure.microsoft.com/fr/services/storage/data-lake-storage

0 votes

La ressource fichier @SaherAhwal n'est pas une ressource blob. Il n'y a pas encore d'API pour renommer un blob dans une opération atomique.

0 votes

@lerthe61 oui, c'est pourquoi vous devez utiliser ADLS Gen 2 et activer l'espace de nommage hiérarchique.

26voto

smarx Points 18006

Vous pouvez toutefois copier et ensuite supprimer.

10 votes

Si vous copiez, assurez-vous de copier les données réelles et les métadonnées, PUIS supprimez. N'utilisez PAS StartCopyFromBlob et supprimez ensuite. J'ai perdu 20 % des fichiers que je renommais parce que la copie ne s'est pas terminée avant que la suppression ne prenne effet. stackoverflow.com/questions/3734672/azure-storage-blob-rename/

23voto

viggity Points 5342

A l'origine, j'utilisais le code de @Zidad, et dans des circonstances de faible charge, il fonctionnait généralement (je renomme presque toujours des petits fichiers, ~10kb).

NE PAS StartCopyFromBlob puis Delete ! !!!!!!!!!!!!!

Dans un scénario de forte charge, J'ai PERDU ~20% des fichiers que je renommais (des milliers de fichiers). . Comme mentionné dans les commentaires sur sa réponse, StartCopyFromBlob ne fait que lancer la copie. Il n'y a aucun moyen pour vous d'attendre que la copie se termine.

La seule façon pour vous de garantir la fin de la copie est de la télécharger et de la retélécharger. Voici mon code mis à jour :

public void Rename(string containerName, string oldFilename, string newFilename)
{
    var oldBlob = GetBlobReference(containerName, oldFilename);
    var newBlob = GetBlobReference(containerName, newFilename);

    using (var stream = new MemoryStream())
    {
        oldBlob.DownloadToStream(stream);
        stream.Seek(0, SeekOrigin.Begin);
        newBlob.UploadFromStream(stream);

        //copy metadata here if you need it too

        oldBlob.Delete();
    }
}

12voto

paqogomez Points 7883

Bien qu'il s'agisse d'un vieux post, peut-être que ce excellent blog post montrera aux autres comment renommer très rapidement les blobs qui ont été téléchargés.

En voici les grandes lignes :

//set the azure container
string blobContainer = "myContainer";
//azure connection string
string dataCenterSettingKey = string.Format("DefaultEndpointsProtocol=https;AccountName={0};AccountKey={1}", "xxxx",
                                            "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx");
//setup the container object
CloudStorageAccount cloudStorageAccount = CloudStorageAccount.Parse(dataCenterSettingKey);
CloudBlobClient blobClient = cloudStorageAccount.CreateCloudBlobClient();
CloudBlobContainer container = blobClient.GetContainerReference(blobContainer);

// Set permissions on the container.
BlobContainerPermissions permissions = new BlobContainerPermissions();
permissions.PublicAccess = BlobContainerPublicAccessType.Blob;
container.SetPermissions(permissions);

//grab the blob
CloudBlob existBlob = container.GetBlobReference("myBlobName");
CloudBlob newBlob = container.GetBlobReference("myNewBlobName");
//create a new blob
newBlob.CopyFromBlob(existBlob);
//delete the old
existBlob.Delete();

1 votes

Pensez à mettre à jour votre réponse avec un bref résumé des points pertinents. Ainsi, elle sera toujours utile aux autres, même si le lien est rompu.

4 votes

D'après ce que j'ai pu constater, cela n'est plus d'actualité depuis Azure Storage API 2... Maintenant CopyFromBlob est devenu StartCopyFromBlob, et j'ai entendu dire que cela met votre blob dans une file d'attente de renommage qui peut prendre au maximum 7 jours !

0 votes

Ce n'est pas mon expérience. Bien que l'ANS puisse indiquer quelque chose de ce genre, il est très rapide à créer et à copier.

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X