如何删除 Azure Blob 容器中的文件夹

Posted

技术标签:

【中文标题】如何删除 Azure Blob 容器中的文件夹【英文标题】:How to delete a folder within an Azure blob container 【发布时间】:2016-04-16 03:12:16 【问题描述】:

我在 Azure 中有一个名为 pictures 的 blob 容器,其中包含各种文件夹(请参见下面的快照):

我正在尝试删除快照中显示的标题为 usersuploads 的文件夹,但我保留了错误:Failed to delete blob pictures/uploads/. Error: The specified blob does not exist. 有人能说明我如何删除这两个文件夹吗?通过谷歌搜索此问题,我无法发现任何有意义的信息。

注意:如果需要,请向我询问更多信息

【问题讨论】:

尝试使用这个客户端azurestorageexplorer.codeplex.com 【参考方案1】:

这是因为“文件夹”实际上并不存在。在 Azure 存储帐户中,您拥有填充有 blob 的容器。您所看到的客户端可视化为“文件夹”的是帐户“图片/上传/”中 blob 的文件名。如果要删除“文件夹”,实际上必须删除每个以相同“路径”命名的 blob。

最常见的方法是获取这些 blob 的列表,然后将其提供给 delete blob 调用。

【讨论】:

好的,但是删除 blob 调用是否可以扩展到例如 20M 个对象? “规模”是一个相对术语。你能删除所有 20M 的 blob 吗?是的,你能在 1 秒内完成吗?不。您将受到 Storage API 限制的限制。 把复选框“全选”也无妨【参考方案2】:

Windows Azure Blob 存储没有文件夹的概念。层次结构非常简单:存储帐户 > 容器 > blob。实际上,删除特定文件夹就是删除所有以该文件夹名称开头的 blob。您可以编写如下简单代码来删除您的文件夹:

CloudStorageAccount storageAccount = CloudStorageAccount.Parse("your storage account");
CloudBlobContainer container = storageAccount.CreateCloudBlobClient().GetContainerReference("pictures");
foreach (IListBlobItem blob in container.GetDirectoryReference("users").ListBlobs(true))

    if (blob.GetType() == typeof(CloudBlob) || blob.GetType().BaseType == typeof(CloudBlob))
    
        ((CloudBlob)blob).DeleteIfExists();
    

container.GetDirectoryReference("users").ListBlobs(true) 列出“图片”容器中以“用户”开头的 blob,然后您可以单独删除它们。要删除其他文件夹,您只需要像这样指定 GetDirectoryReference("your folder name")。

【讨论】:

确实如此。删除文件夹内的 blob 也会删除该文件夹。我们只需要删除文件夹中的所有 blob。 在 ForEach 中你可以使用 CloudBlockBlob 代替 IListBlobItem foreach (var item in items.OfType()) item.Delete(); 它还会删除一个文件夹,比如users2 吗? 对于那些使用Azure.Storage.Blobs v12 寻找最新(截至 2021 年)的用户,请查看下面@Melih 的其他答案:***.com/a/63846242/5101【参考方案3】:

还有一个来自 Microsoft 的桌面存储浏览器。它有一个功能,您可以选择虚拟文件夹,然后将其删除,从而有效地删除所有子 blob。

https://azure.microsoft.com/en-us/features/storage-explorer/

【讨论】:

这确实从点击/脚本中保存,但在内部使用相同的枚举然后删除的机制。所以它可能会轰炸很多删除操作并且很慢,。【参考方案4】:

让我们从一个如何使用 ListBlobsSegmentedAsyc 删除“文件夹”的示例开始:

var container = // get container reference
var ctoken = new BlobContinuationToken();
do

    var result = await container.ListBlobsSegmentedAsync("myfolder", true, BlobListingDetails.None, null, ctoken, null, null);
    ctoken = result.ContinuationToken;
    await Task.WhenAll(result.Results
        .Select(item => (item as CloudBlob)?.DeleteIfExistsAsync())
        .Where(task => task != null)
    );
 while (ctoken != null);

它的作用...

var ctoken = new BlobContinuationToken();

一个“文件夹”可能包含很多文件。 ListBlobSegmentedAsyc 可能只返回其中的一部分。此令牌将存储信息,以便在下次通话中继续。

var result = await container.ListBlobsSegmentedAsync("myfolder", true, BlobListingDetails.None, null, ctoken, null, null);
第一个参数是所需的 blob 名称(“路径”)前缀。 第二个参数“useFlatBlobListing=true”告诉客户端返回所有子文件夹中的所有项目。如果设置为 false,它将以“虚拟文件夹”模式运行,并像文件系统一样运行。 ctoken 将告诉 azure 在哪里继续

有关所有参数,请参阅https://docs.microsoft.com/en-us/dotnet/api/microsoft.windowsazure.storage.blob.cloudblobclient.listblobssegmentedasync?view=azure-dotnet 了解详情。

(item as CloudBlob)?.DeleteIfExistsAsync()

现在我们在 result.Results 中有一个 IListBlobItem 列表。因为不能保证 IListBlobItem 是可删除的 CloudBlob(例如,如果我们设置 useFlatBlobListing=false,它可能是一个虚拟文件夹),我们会尝试强制转换它并在可能的情况下将其删除。

result.Results.Select(item => (item as CloudBlob)?.DeleteIfExistsAsync())

触发删除所有结果并返回任务列表。

.Where(task => task != null)

如果结果包含我们无法转换为 CloudBlob 的项目,我们的任务列表包含空值。我们必须删除它们。

...然后我们等待当前段的所有删除完成并继续下一个段(如果可用)。

【讨论】:

【参考方案5】:

现在您可以使用生命周期管理来删除带有前缀匹配和操作的文件 删除属性daysAfterModificationGreaterThan。让规则保持活动状态约 24 小时。它会完成这项工作。 https://docs.microsoft.com/en-us/azure/storage/blobs/storage-lifecycle-management-concepts

提供生命周期管理文档

【讨论】:

【参考方案6】:

您现在可以使用 ADF 中的删除活动来删除任何文件 /blob。它会删除里面的所有文件

【讨论】:

【参考方案7】:

你也可以在 Azure 云 shell 中进行;这是命令:

az storage blob delete-batch --source <blob-container> --account-name <blob-account> --pattern <folder-name>*

【讨论】:

【参考方案8】:

在最新的存储库 Azure.Storage.Blobs 中,它非常简单

var connectionString = "blob-connection-string";
var containerName = "container-name";
var folderPath = "folder1/subfolder/sub-subfolder";

var blobServiceClient = new BlobServiceClient(connectionString);
var blobContainerClient = blobServiceClient.GetBlobContainerClient(containerName);
var blobItems = blobContainerClient.GetBlobsAsync(prefix: folderPath);
await foreach (BlobItem blobItem in blobItems)

     BlobClient blobClient = blobContainerClient.GetBlobClient(blobItem.Name);
     await blobClient.DeleteIfExistsAsync();

由于每个 blob 都有自己的 uri 值,您可以在查询之前设置前缀,以便它可以获取和删除具有特定 uri 的 blob。随着 blob 被删除,该文件夹将消失。

【讨论】:

【参考方案9】:

尝试使用Azure CLI

例如,如果您想删除以pictures/users 开头的路径,您可以在此处找到所有 blob

export CONN_STRING="<YOUR-CONNECTION-STRING>"

az storage blob list -c mycontainer \
   --connection-string $CONN_STRING \
   --output tsv \
   --prefix pictures/users

或者,也许您想直接删除所有这些:

az storage blob delete-batch -s mycontainer \
   --connection-string $CONN_STRING \
   --pattern pictures/users/*

【讨论】:

【参考方案10】:

WindowsAzure.Storage 包在 9.4.0 版中被拆分为单独的包。这意味着 accepted answer 中使用的 API 在更新的 Azure.Storage.Blobs 包中发生了变化。

以下方法使用较新的 Azure.Storage.Blobs 包中的 API,但仍使用相同的方法来接受答案,即列出所有 blob,然后一次删除一个。

string ConnectionString = "<your connection string>";
string ContainerName = "<your container name>";

private BlobContainerClient ContainerClient()

    var client = new BlobContainerClient(ConnectionString, ContainerName);
    client.CreateIfNotExists();
    return client;


public async Task<List<BlobItem>> ListBlobsAsync(string folder)

    var c = ContainerClient();
    var enumerator = c.GetBlobsByHierarchyAsync(prefix: folder).GetAsyncEnumerator();

    var result = new List<BlobItem>();
    while (await enumerator.MoveNextAsync())
    
        if (enumerator.Current.IsBlob)
            result.Add(enumerator.Current.Blob);
    
    return result;


public async Task DeleteByFolderAsync(string folder)

    var c = ContainerClient();
    foreach (var blob in await ListBlobsAsync(folder))
    
        await c.GetBlobClient(blob.Name).DeleteIfExistsAsync(DeleteSnapshotsOption.IncludeSnapshots);
    

【讨论】:

【参考方案11】:

实现所需行为的一些简单代码:

    public static async Task DeleteFolder(string containerName, string folder)
    
        CloudBlobContainer container = await GetContainerAsync(containerName);

        BlobResultSegment blobList = null;
        bool folderIsEmpty = false;

        while (!folderIsEmpty)
        
            blobList = await container.ListBlobsSegmentedAsync(
                prefix: folder,
                useFlatBlobListing: true,
                blobListingDetails: BlobListingDetails.None,
                maxResults: null,
                currentToken: null,
                options: null,
                operationContext: null
            );

            folderIsEmpty = true;

            foreach (IListBlobItem item in blobList.Results)
            
                folderIsEmpty = false;
                await ((CloudBlockBlob)item).DeleteIfExistsAsync();
            
        
    

【讨论】:

以上是关于如何删除 Azure Blob 容器中的文件夹的主要内容,如果未能解决你的问题,请参考以下文章

Dot.Net Core 中 Azure blob 容器中的软删除 blob 文件

如何在持续时间后删除 blob?

从容器中删除 blob 时如何在 python 中对 Azure PartialBatchErrorException 进行异常处理

下载后如何从 azure blob 存储中删除文件

如何删除 Azure 文件夹中的 blob 文件 [关闭]

如何在说 x 天后定期从 azure 文件共享中删除文件?