HOWTO download a file from a blob container using published AzureFunction

Pavel Kopylov 20 Reputation points
2024-03-13T11:38:35.6266667+00:00

Im trying to download a file from azure blob container uzing already published azure function.

Here is my code example: The function shall download file, given filename in HTTP request.

The function executes without errors, howevever I receive 0 data:

Status: 204 No Content

Size: 0 Bytes

Time: 498 ms

const { app } = require('@azure/functions');

const { BlobServiceClient } = require('@azure/storage-blob');

app.http('GetFile', {

    methods: ['GET'],

    authLevel: 'function',

    handler: async (request, context) => {

        const blobName = request.query.get('filename');

        try {

            const blobServiceClient = BlobServiceClient.fromConnectionString(process.env.BlobConnectionSrtring);

            const containerClient = await blobServiceClient.getContainerClient("sm4updateblobcontainer");

           

            var blobs = await containerClient.listBlobsFlat();

            let i = 1;

            for await (const blob of blobs) {

              console.log(Blob ${i++}: ${blob.name});

            }

           

            const blobClient = containerClient.getBlobClient(blobName);

            const blobExists = await blobClient.exists();

            if (blobExists) {

                // Download the blob's content to a buffer

                const downloadResponse = await blobClient.download();

                const blobStream = downloadResponse.readableStreamBody;

                const contentType = downloadResponse.contentType;

                console.log("Downloading: " + blobName + " : " + downloadResponse.contentLength + " bytes, type: " + contentType);

                context.res = {

                    status: 200,

                    isRaw: true, // This tells Azure Functions that the response is raw binary data

                    body: blobStream,

                    headers: {

                        'Content-Type': contentType

                    }

                }

            } else {

                console.log(blobName + " - Not found");

                context.res = {

                    status: 404,

                    body: Blob ${blobName} does not exist.

                };

            }

        } catch (error) {

            console.log("Error: " + error.message);

            context.res = {

                status: 500,

                body: error.message,

            }

        }

    }

});

Azure Blob Storage
Azure Blob Storage
An Azure service that stores unstructured data in the cloud as blobs.
3,202 questions
0 comments No comments
{count} votes

Accepted answer
  1. JanisP 75 Reputation points
    2024-03-18T06:18:00.77+00:00

    Hi, just replace "context.res" with "return"

    0 comments No comments

4 additional answers

Sort by: Most helpful
  1. Azar 29,520 Reputation points MVP Volunteer Moderator
    2024-03-13T12:13:36.3+00:00

    Hey there Pavel Kopylov

    Great question and thanks for using QandA platform,

    So I think you have a typo in your code where you're accessing the Blob connection string. You wrote process.env.BlobConnectionSrtring instead of process.env.BlobConnectionString. make that your environment variable name matches, I mean instead of string u wrote srtring.

    And also Double-check that the filename you're passing as a query parameter (filename) matches exactly with the name of the blob you're trying to download.

    and see that the content type (contentType) of the blob is correctly set when returning the response.

    If this helps kindly accept the answer thanks much,

    0 comments No comments

  2. Nehruji R 8,181 Reputation points Microsoft External Staff Moderator
    2024-03-14T09:56:20.7833333+00:00

    Hello Pavel Kopylov,

    Greetings! Welcome to Microsoft Q&A forum.

    Your Azure Function code seems to be on the right track, but there are a couple of issues that might be causing this unexpected behavior,

    As above said, In your code you have a typo in the variable name for the BlobServiceClient. It should be BlobServiceClient (with a capital ‘B’), but you’ve used blobserviceclient (all lowercase).

    const blobServiceClient = BlobServiceClient.fromConnectionString(process.env.BlobConnectionSrtring);

    Ensure that the process.env.BlobConnectionSrtring contains the correct connection string for your Azure Blob Storage account.

    Double-check the connection string and make sure it’s valid.

    Consider adding additional logging statements to your function. You can log messages using context.log('Your message here').Check if the blob exists and if the download response is successful. Verify that the blobName parameter from the HTTP request is correctly passed to your function.

    Here’s an updated snippet with the corrections:

    const { app } = require('@azure/functions');

    const { BlobServiceClient } = require('@azure/storage-blob');

    app.http('getfile', {

    methods: ['get'],
    
    authlevel: 'function',
    
    handler: async (request, context) => {
    
        const blobName = request.query.get('filename');
    
        try {
    
            const blobServiceClient = BlobServiceClient.fromConnectionString(process.env.BlobConnectionSrtring);
    
            const containerClient = await blobServiceClient.getContainerClient("sm4updateblobcontainer");
    
            const blobClient = containerClient.getBlobClient(blobName);
    
            const blobExists = await blobClient.exists();
    
            if (blobExists) {
    
                const downloadResponse = await blobClient.download();
    
                const blobStream = downloadResponse.readableStreamBody;
    
                const contentType = downloadResponse.contentType;
    
                context.res = {
    
                    status: 200,
    
                    isRaw: true,
    
                    body: blobStream,
    
                    headers: {
    
                        'Content-Type': contentType
    
                    }
    
                };
    
            } else {
    
                context.res = {
    
                    status: 404,
    
                    body: `Blob ${blobName} does not exist.`
    
                };
    
            }
    
        } catch (error) {
    
            context.res = {
    
                status: 500,
    
                body: error.message
    
            };
    
        }
    
    }
    

    });

    Please replace the connection string and container name with your actual values.

    refer - https://learn.microsoft.com/en-us/azure/storage/blobs/storage-blob-download-java, https://stackoverflow.com/questions/63867939/how-to-read-the-data-from-blob-storage-and-access-it-by-using-azure-function-app, https://www.mssqltips.com/sqlservertip/7532/retrieve-file-azure-blob-storage-azure-function/

    Hope this answer helps! Please let us know if you have any further queries. I’m happy to assist you further.


    Please "Accept the answer” and “up-vote” wherever the information provided helps you, this can be beneficial to other community members.


  3. Pavel Kopylov 20 Reputation points
    2024-03-14T10:37:38.3366667+00:00

    Thank you for the answer,

    Unfortunately I cannot use AzCopy utility because the idea is tommake an Azure Function to do this.

    0 comments No comments

  4. Pavel Kopylov 20 Reputation points
    2024-03-15T07:17:19.7466667+00:00

    Finally found the answer myself.

    I Have noticed, that the function never rerurn anything, also in case of a syntax error.

    So the function was lacking a return statement.

    In fact: all context.res = {...} shall be changed to return {...} in my code.

    The resulting code is:

    const { app } = require('@azure/functions');
    const { BlobServiceClient } = require('@azure/storage-blob');
    
    app.http('GetFile', {
        methods: ['get'],
        authlevel: 'function',
        handler: async (request, context) => {
            const blob_name = request.query.get('filename');
    
            try {
                const blob_service_client = BlobServiceClient.fromConnectionString(process.env.BlobConnectionSrtring);
                const container_client = await blob_service_client.getContainerClient(process.env.BlobContainerName);
                const blob_client = container_client.getBlobClient(blob_name);
                const blob_eists = await blob_client.exists();
                if (blob_eists) {
                    const download_response = await blob_client.download();
                    const blob_stream = download_response.readableStreamBody;
                    const content_type = download_response.contentType;
    
                    context.log("Downloading: " + blob_name + " : " + download_response.contentLength + " bytes, type: " + content_type);
    
                    return {
                        status: 200,
                        isRaw: true,
                        body: blob_stream,
                        headers: {
                            'Content-Type': content_type
                        }
                    };
                } else {
                        context.log("Server error 404, Blob ${blob_name} does not exist.");
        
                        return {
                        status: 404,
                        body: "Blob ${blob_name} does not exist."
                    };
                }
            } catch (error) {
                context.log("Server error 500, " + error.message);
    
                return {
                    status: 500,
                    body: error.message
                };
            }
        }
    });
    
    

Your answer

Answers can be marked as Accepted Answers by the question author, which helps users to know the answer solved the author's problem.