简体   繁体   English

如何使用 c# 获取 Azure Blob 存储容器中现有目录的列表?

[英]How to get a list of existing directories in Azure Blob Storage container using c#?

I have a console app written using C# on the top of Core .NET 2.2 framework.我在 Core .NET 2.2 框架的顶部使用C#编写了一个控制台应用程序。

I am trying to the C# library to get a list of all directories inside my container.我正在尝试使用C# 库获取容器内所有目录的列表。 It is my understanding that Azure Blob Storage does not really have directories.据我了解,Azure Blob 存储实际上并没有目录。 Instead, it creates virtual names that the blobs look like a folder inside a container within browsers like Azure Blob Explorer相反,它会创建虚拟名称,使 blob 看起来像Azure Blob Explorer等浏览器中容器内的文件夹

I store my files using the following code我使用以下代码存储我的文件

CloudBlockBlob blockBlob = container.GetBlockBlobReference("foldername/filename.jpg");

await blockBlob.UploadFromStreamAsync(stream);

So I want to select a distinct list of the prefix aka folder names on inside my container.所以我想在我的容器内选择一个不同的前缀 aka 文件夹名称列表。

So if I have the following blobs "foldername1/file1.jpg", "foldername1/file2.jpg", "foldername1/file3.jpg", and "foldername2/file1.jpg".因此,如果我有以下 Blob“文件夹名1/file1.jpg”、“文件夹名1/file2.jpg”、“文件夹名1/file3.jpg”和“文件夹名2/file1.jpg”。 I want to return "foldername1", "foldername2"我想返回“文件夹名1”、“文件夹名2”

How can I get a list of distinct prefixes from Azure Blob Storage?如何从 Azure Blob 存储获取不同前缀的列表?

Updated更新

I tried to get the feedback from the comments below so I came up with the following code我试图从下面的评论中获得反馈,所以我想出了以下代码

public async Task<string[]> Directories(string path = null)
{
    int index = path == null ? 0 : path.Split('/', StringSplitOptions.RemoveEmptyEntries).Length;

    BlobContinuationToken token = null;
    List<string> directories = new List<string>();
    do
    {
        BlobResultSegment blobsListingResult = await ContainerFactory.Get().ListBlobsSegmentedAsync(path ?? string.Empty, true, BlobListingDetails.None, 5000, token, null, null);
        token = blobsListingResult.ContinuationToken;
        IEnumerable<IListBlobItem> blobsList = blobsListingResult.Results;
        foreach (var item in blobsList)
        {
            var blobName = (item as CloudBlob).Name;
            var blobParts = blobName.Split('/', StringSplitOptions.RemoveEmptyEntries);

            if (blobParts.Length <= index)
            {
                // At this point, we know that this not a directory inside the provided path directory
                continue;
            }

            directories.Add(blobParts[index]);
        }
    }
    while (token != null);

    return directories.Distinct().ToArray();
}

Since I have lots of blobs in the container, this takes way too long because it would have to almost get every single block in order to get a list of the directories.因为我在容器中有很多 blob,所以这需要很长时间,因为它几乎必须获取每个块才能获取目录列表。 Additionally, this may be very costly since I have to read every blob every time this method is called.此外,这可能非常昂贵,因为每次调用此方法时我都必须读取每个 blob。

I essentially need the same result that I would get as running Directory.GetDirectories(path) if everything was running locally!如果一切都在本地运行,我基本上需要与运行Directory.GetDirectories(path)相同的结果! Is there a way to improve this function?有没有办法改进这个功能?

The best way I've found to do this is to not treat the Blob Storage like a folder/file store.我发现这样做的最佳方法是不要将 Blob 存储视为文件夹/文件存储。 Keep the files (blobs) there, but use some other method to track your folder structure.将文件(blob)保留在那里,但使用其他一些方法来跟踪您的文件夹结构。 My method of choice is a SQL database that contains my folder structure, and then a reference to a blob file in Azure.我选择的方法是包含我的文件夹结构的 SQL 数据库,然后是对 Azure 中 blob 文件的引用。 The problem with calling all this code directly in Azure is that:直接在 Azure 中调用所有这些代码的问题在于:

a) It'll be slow b) It'll give you unnecessary cost in the long run a) 它会很慢 b) 从长远来看它会给你带来不必要的成本

You're far better off doing as I suggest, keep metadata elsewhere, and use Blob storage for what its intended for - storing blobs你最好按照我的建议去做,将元数据保存在别处,并使用 Blob 存储来实现它的目的 - 存储 Blob

Maybe you can improve your solution doing a check for the type of blob item?也许您可以通过检查 blob 项目的类型来改进您的解决方案?

        var result = new List<string>();
        var directory = _blobContainer.GetDirectoryReference(relativeFilePath);

        if (directory.Equals(null))
            return result;

        var blobs = directory.ListBlobsSegmentedAsync(null).Result;

        foreach (var item in blobs.Results)
        {
            if (item.GetType() == typeof(CloudBlobDirectory)) 
            {
                result.Add(item.Uri.Segments.Last().Trim('/'));
            }
        }

        return result;

I didn't have too many folders so would be good to double check if the performance meets your requirements.我没有太多文件夹,因此最好仔细检查性能是否满足您的要求。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM