Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Using Azure Function (.NET Core) to Download a file

I have created and HTTP Triggered Azure Function (v2) using .NET Core with the hopes that I can execute the function while passing in some info in the request body and then have the function return/download a file in the browser. Unfortunately I am struggling to get this working.

Below is a snippet of Code

public static async Task<IActionResult> Run([HttpTrigger(AuthorizationLevel.Function, "get", "post", Route = null)]HttpRequest req, ILogger log)
{
    string csv;

    //Do some stuff to create a csv

    byte[] filebytes = Encoding.UTF8.GetBytes(csv);

    req.HttpContext.Response.Headers.Add("content-disposition", "attachment;filename=Export.csv");
    req.HttpContext.Response.ContentType = "application/octet-stream";

    return (ActionResult)new OkObjectResult(filebytes);
}

When I do a post using Postman the request is accepted but the response is 406 "unacceptable" and the output in the log states

"Microsoft.AspNetCore.Mvc.Infrastructure.DefaultOutputFormatterSelector[1] No output formatter was found for content type 'application/octet-stream' to write the response."

I've tried multiple content types including text/plain and text/csv, all give the same response about output formatting.

If I remove or comment out the ContentType the request processes and returns a 200 but the filebytes are returned in the response body instead of being downloaded in the browser.

like image 937
Brian Avatar asked Oct 08 '18 15:10

Brian


People also ask

Does Azure functions support .NET framework?

NET Framework and only supports development in the Azure portal, Azure Stack Hub portal, or locally on Windows computers. This version is in maintenance mode, with enhancements provided only in later versions. Beginning on December 3, 2022, function apps running on versions 2.


1 Answers

You'll need a FileContentResult for this:

public static async Task<IActionResult> Run([HttpTrigger(AuthorizationLevel.Function, "get", "post", Route = null)]HttpRequest req, ILogger log)
{
    string csv;

    //Do some stuff to create a csv

    byte[] filebytes = Encoding.UTF8.GetBytes(csv);

    return new FileContentResult(filebytes, "application/octet-stream") {
        FileDownloadName = "Export.csv"
    };
}

While the comments correctly point out that the ideal solution is to kick off processing in the HTTP function asynchronously, return a 202 Accepted response, save the result to blob storage, have the client wait for processing to complete before starting the blob download and then delete the blob once it's been downloaded, current Azure Functions pricing is only $0.000016/GB-s so you may find that to be unnecessarily complicated unless you have quite high traffic.

like image 193
MarkXA Avatar answered Oct 03 '22 20:10

MarkXA