Azure Storage Blob Rename

Geoff picture Geoff · Sep 17, 2010 · Viewed 39.6k times · Source

Is is possible to rename an Azure Storage Blob using the Azure Storage API from a Web Role? The only solution I have at the moment is to copy the blob to a new blob with the correct name and delete the old one.

Answer

Wiebe Tijsma picture Wiebe Tijsma · Jan 24, 2014

UPDATE:

I updated the code after @IsaacAbrahams comments and @Viggity's answer, this version should prevent you from having to load everything into a MemoryStream, and waits until the copy is completed before deleting the source blob.


For anyone getting late to the party but stumbling on this post using Azure Storage API V2, here's an extension method to do it quick and dirty (+ async version):

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

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

Disclaimer: This is a quick and dirty method to make the rename execute in a synchronous way. It fits my purposes, however as other users noted, copying can take a long time (up to days), so the best way is NOT to perform this in 1 method like this answer but instead:

  • Start the copy process
  • Poll the status of the copy operation
  • Delete the original blob when the copy is completed.