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

时间:2016-03-03 20:17:40

标签: c# azure azure-storage azure-storage-blobs azure-sdk-.net

如何列出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#语法和最佳实践编程模式。简而言之,我希望最终结果尽可能优雅和高效。

如何改进上述代码段?

2 个答案:

答案 0 :(得分:5)

只有您的优雅代码才会问到,它会对存储服务进行过多调用以获取数据。对于每个文件夹/子文件夹,它将转到存储服务并获取数据。

您可以通过列出容器中的所有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);
    }

答案 1 :(得分:1)

我用来获取所有文件和子目录的函数。 请注意在运行函数之前在构造函数或某处分配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;
    }