Azure存储Blob重命名

Geo*_*off 44 c# azure azure-storage

是否可以从Web角色使用Azure存储API重命名Azure存储Blob?我目前唯一的解决方案是将blob复制到具有正确名称的新blob并删除旧的blob.

Wie*_*sma 40

更新:

我在@IsaacAbrahams注释和@Viggity的答案后更新了代码,这个版本应该可以防止你必须将所有内容加载到MemoryStream中,并等待复制完成后再删除源blob.


对于任何迟到的人,但使用Azure Storage API V2绊倒这篇文章,这里有一个快速和脏(+异步版本)的扩展方法:

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();
    }
}
Run Code Online (Sandbox Code Playgroud)

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();            
    }
Run Code Online (Sandbox Code Playgroud)

免责声明:这是一种快速而又脏的方法,可以使重命名以同步方式执行.它符合我的目的,但是正如其他用户指出的那样,复制可能需要很长时间(最多几天),所以最好的方法是不要像这个答案那样在1方法中执行此操作,而是:

  • 开始复制过程
  • 轮询复制操作的状态
  • 复制完成后删除原始blob.

  • 在高负载的情况下,我丢失了大约20%的重命名文件,因为删除打败了副本.操作不要排队.修复此处:http://stackoverflow.com/questions/3734672/azure-storage-blob-rename/26549519#26549519 (3认同)
  • @Vikram如果我快速看一下,您不是在异步操作上使用“ await”。我认为您应该首先研究C#中async / await构造的基础,然后提出一个新问题(如果要我回答,请单击此处),这应该给您一个更好的答案。 (2认同)

Rin*_*lin 30

这样做的可行之路,虽然Azure的blob服务API不直接支持重命名或移动斑点的能力.


use*_*559 26

但是,您可以复制然后删除.

  • 如果您复制,请确保复制实际数据和元数据,然后删除.不要使用StartCopyFromBlob然后删除.我丢失了20%的文件我正在重命名,因为复制没有在删除生效之前完成.http://stackoverflow.com/questions/3734672/azure-storage-blob-rename/26549519#26549519 (9认同)

vig*_*ity 19

我最初使用来自@Zidad的代码,并且在低负载情况下它通常有效(我几乎总是重命名小文件,~10kb).

切勿StartCopyFromBlobDelete!!!!!!!!!!!!!!

在高负载情况下,我丢失了大约20%的重命名文件(数千个文件).正如他对答案的评论中提到的,StartCopyFromBlob只需启动副本.您无法等待副本完成.

保证复制完成的唯一方法是下载并重新上传.这是我更新的代码:

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();
    }
}
Run Code Online (Sandbox Code Playgroud)

  • 显然,您也可以检查一个状态,它允许您重命名该 blob,而不必像您一样将其全部下载到内存中,我将更新我的答案...... (2认同)
  • 为什么人们会像这样滥用 MemoryStreams?这太糟糕了。您可以使用小的 `byte` 缓冲区将 `oldBlob` 流直接通过管道传输到 `newBlob` 流中。这完全违背了 `Stream` 的目的,并且完全不可扩展。我已经看到同样的代码被复制到生产环境中,它导致了 OOM 问题。糟糕的。 (2认同)

paq*_*mez 12

虽然这是一篇旧文章,但也许​​这篇优秀的博客文章会向其他人展示如何快速重命名已上传的blob.

以下是亮点:

//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();
Run Code Online (Sandbox Code Playgroud)

  • 据我所知,Azure Storage API 2已经过时了......现在CopyFromBlob已成为StartCopyFromBlob,我听说这会将你的blob放入一个最多可能需要7天的重命名队列! (4认同)
  • v2 api将CopyFromBlob转换为StartCopyFromBlob.在高负载情况下,我丢失了20%的重命名文件.不好.http://stackoverflow.com/questions/3734672/azure-storage-blob-rename/26549519#26549519 (2认同)

Alb*_*rtK 8

重命名是不可能的。以下是使用Azure SDK for .NET v12 的解决方法:

BlobClient sourceBlob = container.GetBlobClient(sourceBlobName);
BlobClient destBlob = container.GetBlobClient(destBlobName);
CopyFromUriOperation ops = await destBlob.StartCopyFromUriAsync(sourceBlob.Uri);

long copiedContentLength = 0;
while (ops.HasCompleted == false)
{
    copiedContentLength = await ops.WaitForCompletionAsync();
    await Task.Delay(100);
}
await sourceBlob.DeleteAsync();
Run Code Online (Sandbox Code Playgroud)


Ann*_* Yu 6

复制blob,然后删除它.

测试1G大小的文件,它工作正常.

有关详细信息,请参阅 MSDN上的示例.

StorageCredentials cred = new StorageCredentials("[Your?storage?account?name]", "[Your?storage?account?key]");  
CloudBlobContainer container = new CloudBlobContainer(new Uri("http://[Your?storage?account?name].blob.core.windows.net/[Your container name] /"), cred);  

string fileName = "OldFileName";  
string newFileName = "NewFileName";  
await container.CreateIfNotExistsAsync();  

CloudBlockBlob blobCopy = container.GetBlockBlobReference(newFileName);  

if (!await blobCopy.ExistsAsync())  
{  
    CloudBlockBlob blob = container.GetBlockBlobReference(fileName);  

    if (await blob.ExistsAsync())  
    {  
           // copy
           await blobCopy.StartCopyAsync(blob);                               
           // then delete
           await blob.DeleteIfExistsAsync();  
    } 
} 
Run Code Online (Sandbox Code Playgroud)