2
votes

I recently discovered the magic of being able to run an ASP.NET Core 3 - Web API project deployed as a single Lambda function in AWS behind AWS API Gateway (https://aws.amazon.com/blogs/developer/deploy-an-existing-asp-net-core-web-api-to-aws-lambda/). I have been successful at deploying and interacting with my project's API via the browser and Postman - hitting APIs that return responses with single values or C# objects serialized as a JSON. I specifically used the Serverless framework (https://www.serverless.com/) to deploy the solution in my account.

However, when adding an endpoint to my Controller with the intention of serving up a static file, specifically an image that is part of the project (bundled in my deployment package) - I get an HTTP 200 OK when running locally and the file and an HTTP 200 OK but an empty body. Follow up requests to the deployed API Gateway endpoint return HTTP 304 but still an empty body.

Since the method on the controller works successfully locally serving up the file, I figured there might be some additional configuration or limitation to having this kind of functionality when the solution is deployed as a Lambda function via API Gateway.

I tried a few different approaches but the below works locally but not when deployed to AWS.

    [HttpGet("Image2")]
    public IActionResult GetImage2()
    {
        string imagePath = "assets/baby-yoda.jpg";
        byte[] imageBytes = System.IO.File.ReadAllBytes(imagePath);
        return PhysicalFile(Path.Join(Directory.GetCurrentDirectory(), imagePath), "image/jpeg", "image.jpg");
    }

My serverless.yml has been updated to include:

provider:
    apiGateway:
        binaryMediaType:
        - '*/*

This now has the file be downloaded by the browser when the endpoint is hit -- however, the file appears to be larger then the original (429kb vs 324kb) and is corrupt/can't be opened ("It looks like we don't support this file format."

1
What is your serverless yml config for this API call? I believe that you should look for that config first to see how to set up an API to that returns a file.Bemn
Provided ApiGateway details/update from serverless.yml file.smk081
Hi do you have any solution for this?wapt49

1 Answers

0
votes

On the Init() method on LambdaEntryPoint class (the method that you are registering with AWS Lambda as the "Handler" for your Lambda function) we needed to add some additional registration calls to whitelist the file formats (content type) that should be serialized to Base64 before returning to API Gateway.

namespace ProjectNameHere
{
    public class LambdaEntryPoint : Amazon.Lambda.AspNetCoreServer.APIGatewayProxyFunction
    {
        protected override void Init(IWebHostBuilder builder)
        {

            RegisterResponseContentEncodingForContentType("image/jpeg", ResponseContentEncoding.Base64);
            RegisterResponseContentEncodingForContentType("application/vnd.openxmlformats-officedocument.spreadsheetml.sheet", ResponseContentEncoding.Base64);
            RegisterResponseContentEncodingForContentType("application/vnd.openxmlformats-officedocument.wordprocessingml.document", ResponseContentEncoding.Base64);

            builder
                .UseStartup<Startup>();
        }
    }
}

Then your Controllers can just return the File through the normal via ActionResult (File, FileStreamResult, FileContentResult, etc.):

[HttpGet("File")]
public async Task<ActionResult> File()
{
    try
    {
        var requestedFile = FileDictionary[1];
        return File(requestedFile.Bytes, requestedFile.MimeType);
    }
    catch (Exception ex)
    {
        _logger.LogError(ex.Message);
        _logger.LogError(ex.InnerException?.Message);
        return BadRequest();
    }
}