如何使用适用于 .NET 的 Azure 存储客户端库 (BLOBS) 列出所有虚拟目录和子目录

本文关键字:虚拟 子目录 BLOBS NET 适用于 何使用 Azure 存储 客户端 | 更新日期: 2023-09-27 18:37:26

如何列出blob容器中的所有目录和子目录?

这是我到目前为止所拥有的:

public List<CloudBlobDirectory> Folders { get; set; }
public List<CloudBlobDirectory> GetAllFoldersAndSubFoldersFromBlobStorageContainer()
{
    CloudStorageAccount storageAccount = CloudStorageAccount.Parse(ConfigurationManager.ConnectionStrings["StorageConnectionString"].ConnectionString);
    CloudBlobClient blobClient = storageAccount.CreateCloudBlobClient();
    CloudBlobContainer container = blobClient.GetContainerReference("mycontainer");
    if (container.Exists())
    {
        Folders = new List<CloudBlobDirectory>();
        foreach (var item in container.ListBlobs())
        {
            if (item is CloudBlobDirectory)
            {
                var folder = (CloudBlobDirectory)item;
                Folders.Add(folder);
                GetSubFolders(folder);
            }
        }
    }
    return Folders;
}
private void GetSubFolders(CloudBlobDirectory folder)
{
    foreach (var item in folder.ListBlobs())
    {
        if (item is CloudBlobDirectory)
        {
            var subfolder = (CloudBlobDirectory)item;
            Folders.Add(subfolder);
            GetSubFolders(subfolder);
        }
    }
}

上面的代码片段给了我想要的列表,但我不确定递归方法和其他 .NET/C# 语法和最佳实践编程模式。简而言之,我希望最终结果尽可能优雅和高性能。

如何改进上面的代码片段?

如何使用适用于 .NET 的 Azure 存储客户端库 (BLOBS) 列出所有虚拟目录和子目录

其他非常优雅的代码的唯一问题是它对存储服务进行了太多调用来获取数据。对于每个文件夹/子文件夹,它转到存储服务并获取数据。

可以通过列出容器中的所有 blob 来避免这种情况,然后确定它是客户端上的目录还是 Blob。例如,看看这里的代码(它不像你的那么优雅,但希望它应该让你了解我想要传达的内容):

    static void FetchCloudBlobDirectories()
    {
        var account = new CloudStorageAccount(new StorageCredentials(accountName, accountKey), true);
        var containerName = "container-name";
        var blobClient = account.CreateCloudBlobClient();
        var container = blobClient.GetContainerReference(containerName);
        var containerUrl = container.Uri.AbsoluteUri;
        BlobContinuationToken token = null;
        List<string> blobDirectories = new List<string>();
        List<CloudBlobDirectory> cloudBlobDirectories = new List<CloudBlobDirectory>();
        do
        {
            var blobPrefix = "";//We want to fetch all blobs.
            var useFlatBlobListing = true;//This will ensure all blobs are listed.
            var blobsListingResult = container.ListBlobsSegmented(blobPrefix, useFlatBlobListing, BlobListingDetails.None, 500, token, null, null);
            token = blobsListingResult.ContinuationToken;
            var blobsList = blobsListingResult.Results;
            foreach (var item in blobsList)
            {
                var blobName = (item as CloudBlob).Name;
                var blobNameArray = blobName.Split(new string[] { "/" }, StringSplitOptions.RemoveEmptyEntries);
                //If the blob is in a virtual folder/sub folder, it will have a "/" in its name.
                //By splitting it, we are making sure that it is indeed the case.
                if (blobNameArray.Length > 1)
                {
                    StringBuilder sb = new StringBuilder();
                    //Since the blob name (somefile.png) will be the last element of this array and we're not interested in this,
                    //We only iterate through 2nd last element.
                    for (var i=0; i<blobNameArray.Length-1; i++)
                    {
                        sb.AppendFormat("{0}/", blobNameArray[i]);
                        var blobDirectory = sb.ToString();
                        if (blobDirectories.IndexOf(blobDirectory) == -1)//We check if we have already added this to our list or not
                        {
                            blobDirectories.Add(blobDirectory);
                            var cloudBlobDirectory = container.GetDirectoryReference(blobDirectory);
                            cloudBlobDirectories.Add(cloudBlobDirectory);
                            Console.WriteLine(cloudBlobDirectory.Uri);
                        }
                    }
                }
            }
        }
        while (token != null);
    }

我的函数我用来获取所有文件和子目录。请注意,在运行函数之前,要在构造函数中或某个地方分配 BlobContainer 对象,这样它就不会为每个文件/目录调用它

  public IEnumerable<String> getAllFiles(string prefix, bool slash = false) //Prefix for, slash for recur, see folders
    { 
        List<String> FileList = new List<string>();
        if (!BlobContainer.Exists()) return FileList; //BlobContainer is defined in class before this is run
        var items = BlobContainer.ListBlobs(prefix);
        foreach (var blob in items)
        {
            String FileName = "";
            if (blob.GetType() == typeof(CloudBlockBlob))
            {
                FileName = ((CloudBlockBlob)blob).Name;
                if (slash) FileName.Remove(0, 1); //remove slash if file
                FileList.Add(FileName);
            }
            else if (blob.GetType() == typeof(CloudBlobDirectory))
            {
                FileName = ((CloudBlobDirectory)blob).Prefix;
                IEnumerable<String> SubFileList = getAllFiles(FileName, true);
                foreach (String s in SubFileList)
                {
                    FileList.Add(s);
                }
            }
        }
        return FileList;
    }