How to retrieve blobs within a blob directory path using the Azure.Storage.Blobs BlobClient?
Asked Answered
F

2

10

I'm not seeing any examples online on how to get all the blobs located inside a certain directory within a BlobContainerClient.

Previously, I was using the Microsoft.Azure.Storage packages, but those have since been deprecated. My old code that was scanning a directory for all blobs was:

public async Task<void> ListAllBlobs(string path)
{
    var myContainer = await GetCloudBlobClientAsync();
    var directory = myContainer.GetDirectoryReference(path);
    var blobs = await directory.ListBlobsSegmentedAsync(true, BlobListingDetails.None, 
        blobSettings.MaxResult, null, null, null);
    var results = blobs.Results;

    foreach(CloudBlockBlob b in results)
    {
        // non-relevant code
    }
}

private async Task<CloudBlobContainer> GetCloudBlobClientAsync()
{
    var storageAccount = CloudStorageAccount.Parse(azureBlobStorageConnectionString);
    var blobClient = storageAccount.CreateCloudBlobClient();
    var container = blobClient.GetContainerReference(blobStorageSettings.ContainerName);

    if (!await container.ExistsAsync())
    {
        await container.CreateAsync();
    }

    return container;
}

Essentially, I'm moving the above code from Microsoft.Azure.Storage over to Azure.Storage.Blobs.

If I were to recreate the ListAllBlobs(string path) function to use Azure.Storage.Blobs, I'm confused on how to setup a container and then access an inner container based on a path that's passed in - then cycle through the blobs that exist within that container. Can anyone help?

Here's what I have so far:

public async Task<void> ListAllBlobs(string path)
{
    var myContainer = await GetCloudBlobClientAsync();
    var directory = myContainer.GetBlobClient(path);

    // This doesn't work because I can't do 'GetBlobs' on the Client, only on the container.
    foreach(BlobItem blob in directory.GetBlobs(Blobtraits.None, BlobStates.None, string.Empty))
    {
        // more non-relevant code
    }
}

To clarify, in the above code, it doesn't like that I'm calling GetBlobs on a Client, rather than on the Container, but I can't pass in a path to the container.

Flick answered 19/1, 2022 at 22:57 Comment(0)
F
5

You were almost there. You would still use BlobContainerClient and call GetBlobsAsync method on that. What you missed is that you will need to set the prefix parameter's value as the path.

So your code would be something like:

var myContainer = await GetCloudBlobClientAsync();
var blobsListingResult = await myContainer.GetBlobsAsync(prefix=path);

UPDATE

Please try the following code:

var myContainer = await GetCloudBlobClientAsync();
await foreach (BlobItem blob in myContainer.GetBlobsAsync(BlobTraits.None, BlobStates.None, path))
{
  names.Add(blob.Name);
}
Fabrianne answered 20/1, 2022 at 5:2 Comment(6)
The only issue now is when I do GetBlobsAsync(prefix=path), the error is "The name 'prefix' does not exist in the current context"Flick
If I do GetBlobsAsync(BlobTraits.None, BlobStates.None, path), the error is "'AsyncPageable<BlobItem>' does not contain a definition for 'GetAwaiter'..."Flick
Updated my answer with modified code. Please give that a try.Fabrianne
You're the bomb, this was exactly what I was missing, thanks!Flick
Out of curiousity, within that foreach loop you're doing above, how would you go about a Delete Blob. The the deprecated SDK v11, it was simple: await blob.DeleteAsync(),Flick
Using the blob name and the container client you will need to create an instance of BlobClient using GetBlobClient method and then you would call DeleteAsync method on that object.Fabrianne
D
6

Try this ...

static async Task GetBlobs()
{
    string connectionString = "<connection_string>";
    string containerName = "<container_name>";

    var blobContainerClient = new BlobContainerClient(connectionString, containerName);

    var blobs = blobContainerClient.GetBlobs(Azure.Storage.Blobs.Models.BlobTraits.All, Azure.Storage.Blobs.Models.BlobStates.All,
        "YourPrefix");

    foreach (var blob in blobs)
    {
        Console.WriteLine(blob.Name); 
    }
}

... that worked for me.

Example

Discreditable answered 20/1, 2022 at 5:0 Comment(3)
Sadly, this solution does not work. The error on directory.GetBlobs is "'BlobClient' does not contain a definition for 'GetBlobs' and no accessible extension method 'GetBlobs' accepting a first argument of type 'BlobClient' could be found."Flick
In my haste to fix my answer, I realised I omitted a fairly important line of code, which, may or may not help you get with your question. The object I am instantiating (BlobContainerClient) is a little different to the way you're doing it. Does that help?Discreditable
Thank you this was great help for the approach you took!Flick
F
5

You were almost there. You would still use BlobContainerClient and call GetBlobsAsync method on that. What you missed is that you will need to set the prefix parameter's value as the path.

So your code would be something like:

var myContainer = await GetCloudBlobClientAsync();
var blobsListingResult = await myContainer.GetBlobsAsync(prefix=path);

UPDATE

Please try the following code:

var myContainer = await GetCloudBlobClientAsync();
await foreach (BlobItem blob in myContainer.GetBlobsAsync(BlobTraits.None, BlobStates.None, path))
{
  names.Add(blob.Name);
}
Fabrianne answered 20/1, 2022 at 5:2 Comment(6)
The only issue now is when I do GetBlobsAsync(prefix=path), the error is "The name 'prefix' does not exist in the current context"Flick
If I do GetBlobsAsync(BlobTraits.None, BlobStates.None, path), the error is "'AsyncPageable<BlobItem>' does not contain a definition for 'GetAwaiter'..."Flick
Updated my answer with modified code. Please give that a try.Fabrianne
You're the bomb, this was exactly what I was missing, thanks!Flick
Out of curiousity, within that foreach loop you're doing above, how would you go about a Delete Blob. The the deprecated SDK v11, it was simple: await blob.DeleteAsync(),Flick
Using the blob name and the container client you will need to create an instance of BlobClient using GetBlobClient method and then you would call DeleteAsync method on that object.Fabrianne

© 2022 - 2024 — McMap. All rights reserved.