【问题标题】:How to get a list of existing directories in Azure Blob Storage container using c#?如何使用 c# 获取 Azure Blob 存储容器中现有目录的列表?
【发布时间】:2019-06-28 18:57:58
【问题描述】:

我有一个使用 C# 在 Core .NET 2.2 框架之上编写的控制台应用程序。

我正在尝试通过C# library 获取容器内所有目录的列表。据我了解,Azure Blob 存储实际上并没有目录。相反,它会创建虚拟名称,使 blob 看起来像 Azure Blob Explorer 等浏览器中容器内的文件夹

我使用以下代码存储我的文件

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

await blockBlob.UploadFromStreamAsync(stream);

所以我想在我的容器中选择一个不同的前缀列表,也就是文件夹名称。

因此,如果我有以下 blob “foldername1/file1.jpg”、“foldername1/file2.jpg”、“foldername1/file3.jpg”和“foldername2/file1.jpg”。我想返回“文件夹名1”、“文件夹名2”

如何从 Azure Blob 存储中获取不同前缀的列表?

更新

我试图从下面的 cmets 获得反馈,所以我想出了以下代码

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

由于容器中有很多 blob,这需要很长时间,因为它几乎必须获取每个块才能获取目录列表。此外,这可能会非常昂贵,因为每次调用此方法时我都必须读取每个 blob。

如果一切都在本地运行,我基本上需要与运行Directory.GetDirectories(path) 相同的结果! 有没有办法改进这个功能?

【问题讨论】:

  • Azure Blob 存储中实际上没有文件夹,它们是“虚拟的”并调用前缀。我认为您没有空文件夹/前缀。要获取所有这些,您可能必须枚举所有 blob,收集它们的所有前缀并调用 Distinct()。
  • 您应该查看this answer,它回答了一个非常相似(几乎相同)的问题。
  • @DavidMakogon 在查看了你给我的答案后,我更新了我的问题。

标签: c# azure azure-blob-storage


【解决方案1】:

我发现这样做的最佳方法是不要将 Blob 存储视为文件夹/文件存储。将文件(blob)保留在那里,但使用其他方法来跟踪您的文件夹结构。我选择的方法是包含我的文件夹结构的 SQL 数据库,然后是对 Azure 中的 blob 文件的引用。在 Azure 中直接调用所有这些代码的问题在于:

a) 会很慢 b) 从长远来看,它会给你带来不必要的成本

你最好按照我的建议去做,将元数据保存在别处,并使用 Blob 存储来实现其预期用途 - 存储 Blob

【讨论】:

    【解决方案2】:

    也许您可以通过检查 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;
    

    我没有太多文件夹,所以最好仔细检查一下性能是否符合您的要求。

    【讨论】:

      猜你喜欢
      • 2020-07-04
      • 2021-02-03
      • 1970-01-01
      • 1970-01-01
      • 2015-12-19
      • 2021-10-10
      • 2021-04-22
      • 2020-09-05
      • 2015-11-10
      相关资源
      最近更新 更多