简体   繁体   中英

How to list all virtual directories and subdirectories using Azure Storage Client Library for .NET (BLOBS)

How to list ALL directories AND subdirectories in a blob container?

This is what I have so far:

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

The above code-snippet gives me the list that I want but I am unsure about the recursive method and other .NET/C# syntax and best practice programming patterns. Simply put, I would like the end result to be as elegant and as performant as possible.

How can the above code-snippet be improved?

Only issue with your otherwise very elegant code is that it makes too many calls to storage service to fetch the data. For each folder/sub folder, it goes to the storage service and gets the data.

You could avoid that by list all blobs from a container and then figure out if it is a directory or blob on the client side. For example, take a look at this code here (It's not as elegant is yours but hopefully it should give you an idea about what I am trying to convey):

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

My function I use to get all the files and sub directories. Please note to assign your BlobContainer object in the constructor or somewhere before running the function so it wont call it for every file/directory

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

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

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