如何删除 Azure Blob 容器中的文件夹
Posted
技术标签:
【中文标题】如何删除 Azure Blob 容器中的文件夹【英文标题】:How to delete a folder within an Azure blob container 【发布时间】:2016-04-16 03:12:16 【问题描述】:我在 Azure 中有一个名为 pictures
的 blob 容器,其中包含各种文件夹(请参见下面的快照):
我正在尝试删除快照中显示的标题为 users
和 uploads
的文件夹,但我保留了错误: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.OfTypeusers2
吗?
对于那些使用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 时如何在 python 中对 Azure PartialBatchErrorException 进行异常处理