Warning: file_get_contents(/data/phpspider/zhask/data//catemap/0/azure/13.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
如何删除Azure blob容器中的文件夹_Azure_Azure Storage_Azure Storage Blobs - Fatal编程技术网

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

如何删除Azure blob容器中的文件夹,azure,azure-storage,azure-storage-blobs,Azure,Azure Storage,Azure Storage Blobs,我在Azure中有一个名为pictures的blob容器,其中包含各种文件夹(请参见下面的快照): 我试图删除快照中显示的标题为users和uploads的文件夹,但我保留了错误:无法删除blob图片/上传/。错误:指定的blob不存在。有人能告诉我如何删除这两个文件夹吗?通过谷歌搜索这个问题,我还没有发现任何有意义的东西 注意:如果您需要更多信息,请询问我,因为“文件夹”实际上不存在。在Azure存储帐户中,您有装满blob的容器。客户机所看到的“文件夹”是帐户“pictures/uploa

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

我试图删除快照中显示的标题为
users
uploads
的文件夹,但我保留了错误:
无法删除blob图片/上传/。错误:指定的blob不存在。
有人能告诉我如何删除这两个文件夹吗?通过谷歌搜索这个问题,我还没有发现任何有意义的东西

注意:如果您需要更多信息,请询问我,因为“文件夹”实际上不存在。在Azure存储帐户中,您有装满blob的容器。客户机所看到的“文件夹”是帐户“pictures/uploads/”中blob的文件名。如果要删除“文件夹”,实际上必须删除使用相同“路径”命名的每个blob


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

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(“用户”).ListBlobs(true)列出“图片”容器中以“用户”开头的Blob,然后可以单独删除它们。要删除其他文件夹,您只需像下面这样指定GetDirectoryReference(“您的文件夹名称”)。

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


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

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();
“文件夹”可能包含很多文件。ListBlobSegmentedAsync只能返回其中的一部分。此令牌将存储下一次呼叫中要继续的信息

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

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

result.Results.Select(item => (item as CloudBlob)?.DeleteIfExistsAsync())
触发删除所有结果并返回任务列表

.Where(task => task != null)
如果结果包含无法强制转换到CloudBlob的项,则任务列表包含空值。我们必须移除它们


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

现在,您可以使用生命周期管理删除带有前缀匹配的文件,并对其执行操作 使用属性
daysaftermodificationgreater删除
。让规则保持活动状态约24小时。它会完成任务的。有关生命周期管理的文档,请访问

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

你也可以在Azure cloud shell中执行此操作;命令如下:

az storage blob delete-batch --source <blob-container> --account-name <blob-account> --pattern <folder-name>*
az存储blob删除批处理--源--帐户名--模式*

在最新的回购协议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时,文件夹将消失。

尝试使用 例如,如果要删除以
pictures/users
开头的路径,可以在此处找到所有blob

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

az storage blob list -c mycontainer \
   --connection-string $CONN_STRING \
   --output tsv \
   --prefix pictures/users
在版本9.4.0中,该包被拆分为单独的包。这意味着中使用的API在较新的包中已更改

下面的方法使用较新包中的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);
    }
}
字符串连接字符串=”;
字符串ContainerName=“”;
私有BlobContainerClient容器客户端()
{
var client=新的BlobContainerClient(ConnectionString,ContainerName);
CreateIfNotExists();
返回客户;
}
公共异步任务ListBlobsAsync(字符串文件夹)
{
var c=容器客户端();
var enumerator=c.GetBlobsByHierarchyAsync(前缀:folder).GetAsyncEnumerator();
var result=新列表();
while(等待枚举器.MoveNextAsync())
{
if(枚举数.Current.IsBlob)
添加(枚举数.Current.Blob);
}
返回结果;
}
公共异步任务DeleteByFolderAsync(字符串文件夹)
{
var c=容器客户端();
foreach(等待列表BlobsAsync(文件夹)中的var blob)
{
等待c.GetBlobClient(blob.Name).DeleteIfExistsAsync(DeleteSnapshotsOption.IncludeSnapshots);
}
}

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

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

试着使用这个客户端,好吧,但是deleteblob调用scale到,比如说,20M对象吗?“scale”是一个相对的术语。你能删除所有2000万个blob吗?是的,你能在1秒钟内完成吗?不可以。您将受到存储API限制的限制。选中“全选”复选框不会有什么坏处,尽管这确实可以从单击/脚本中保存,但使用相同的枚举,然后在其中逐个删除。因此,它可能会轰炸大量的删除操作,并且是缓慢的。这是真的。删除文件夹中的blob也会删除文件夹。我们只需要删除文件夹中的所有Blob。在ForEach中,您可以使用CloudBlockBlob而不是IListBlobItemforeach(items.OfType中的var item)
    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();
            }
        }
    }