2

I am trying to download blob using blob url in Service Bus Topic trigger Azure function, but getting below error:

Status: 404 (The specified blob does not exist.)
 ErrorCode: BlobNotFound
Content:
<?xml version="1.0" encoding="utf-8"?><Error><Code>BlobNotFound</Code><Message>The specified blob does not exist.
</Message></Error>

Below is my Startup.cs file:

[assembly: FunctionsStartup(typeof(Startup))]
namespace Emails.Dispatcher
{
    public class Startup : FunctionsStartup
    {
        public override void Configure(IFunctionsHostBuilder builder)
        {
            builder.Services.AddSingleton(x =>
            new BlobServiceClient(connectionString: Environment.GetEnvironmentVariable("AzureWebJobsStorage")));

            builder.Services.AddSingleton<IBlobService, BlobService>();

            builder.Services.AddLogging();
            builder.Services.AddHttpClient();
            builder.AddHelpers();
            builder.Services.AddWorkers();

        }
    }
}

BlobService:

public class BlobService : IBlobService
{
    private readonly BlobServiceClient _blobServiceClient;

    public BlobService(BlobServiceClient blobServiceClient)
    {
        this._blobServiceClient = blobServiceClient;
    }

    public async Task<byte[]> DownloadAsync(string containerName, string fileUri)
    {
        var containerClient = _blobServiceClient.GetBlobContainerClient(containerName);

        var blobClient = containerClient.GetBlobClient(fileUri);

        using (var ms = new MemoryStream())
        {
            await blobClient.DownloadStreamingAsync();
            return ms.ToArray();
        }
    }

    public async Task<BlobDto> UploadAsync(string containerName, string filename, string content)
    {
        var containerClient = _blobServiceClient.GetBlobContainerClient(containerName);

        var blobClient = containerClient.GetBlobClient(filename);

        var bytes = Encoding.UTF8.GetBytes(content);

        await using var memoryStream = new MemoryStream(bytes);

        await blobClient.UploadAsync(content);

        return new BlobDto
        {
            Uri = blobClient.Uri,
            Name = blobClient.Name
        };
    }
}

public interface IBlobService
{
    Task<BlobDto> UploadAsync(string containerName, string filename, string content);

    Task<byte[]> DownloadAsync(string containerName, string fileUri);
}

Actually this service is receiving full blob url (i.e. https://{storage-url}.blob.core.windows.net/{container-name}/files/unzip/691ec307-7c2b-4aaa-8f75-8742c9faa9f5/1615015726/{file-name}.pdf).

Am i missing anythigng here?

3 Answers 3

2

I am able to download blob file with the help of Uri and and Name property of CloudBlockBlob. As shown below:

  public async Task<byte[]> DownloadAsync(string containerName, string fileUri)
        {
            var containerClient = _blobServiceClient.GetBlobContainerClient(containerName);

            var blobUri = new System.Uri(fileUri);

            var name = new CloudBlockBlob(blobUri).Name;

            var blobClient = containerClient.GetBlobClient(name);

            var response = await blobClient.DownloadStreamingAsync();

            using MemoryStream ms = new MemoryStream();

            await response.Value.Content.CopyToAsync(ms);

            ms.Position = 0;

            return ms.ToArray();
        }
Sign up to request clarification or add additional context in comments.

Comments

1

The issue is with the following line of code:

var blobClient = containerClient.GetBlobClient(fileUri);

When you create a BlobClient using ContainerClient and GetBlobClient, you need to provide just the name of the blob and not the entire URL.

To fix the issue, just pass the blob name.

4 Comments

Actually this service is receiving full blob url, for example - https://{storage-url}.blob.core.windows.net/{container-name}/files/unzip/691ec307-7c2b-4aaa-8f75-8742c9faa9f5/1615015726/{file-name}.pdf. How should I identity the blob name in this url?
You could create a Uri object from the url and parse it to get the blob name. How are you creating blob service client BTW?
BlobServiceClient i am intializing in the Startup.cs, as shown in the question. (builder.Services.AddSingleton(x => new BlobServiceClient(connectionString: Environment.GetEnvironmentVariable("AzureWebJobsStorage")));
Thanks! @Gaurav Mantri, I am to download blob file as you suggested, I used Uri and Name property of CloudBlockBlob
0

You likely have unallocated strings in the blob name.

Workaround that works: replace segment number with your file container segment number and use replace to fix the unknown file name character.

CloudBlobDirectory dira = Container.GetDirectoryReference(string.Empty);
var rootDirFolders = dira.ListBlobsSegmentedAsync(true, BlobListingDetails.Metadata, null, null, null, null).Result.Results;
foreach (var blob in rootDirFolders)
{
    var blockBlob = Container.GetBlockBlobReference(blob.StorageUri.PrimaryUri.Segments[2].Replace("%20", " "));
    var blockBlobRecent = blockBlob.Name.Contains(formatdateValue); //filters blobs by date. Standard practice is that each blob has date in the name. Avoid using Modified date as filter
    if (blockBlobRecent)
    {
        string localPath = DownloadPath + blob.StorageUri.PrimaryUri.Segments[2].Replace("%20", " ");
        string localPathfinal = localPath.Replace("%20", " ");
        await blockBlob.DownloadToFileAsync(localPathfinal, FileMode.Create).ConfigureAwait(false);
    }
    else
    {
        //do nothing
    }
}

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.