'AWS Lambda fails to return PDF file

I have created a lambda function using serverless. This function is fired via API Gateway on a GET request and should return a pdf file from a buffer. I'm using html-pdf to create the buffer and trying to return the pdf file with the following command

  let response = {
    statusCode: 200,
    headers: {'Content-type' : 'application/pdf'},
    body: buffer.toString('base64'),
    isBase64Encoded : true,
  };
  return callback(null, response);

but the browser is just failing to load the pdf, so I don't know exactly how to return the pdf file directly to the browser. Could'nt find a solution for that.



Solution 1:[1]

After spending several hours on this I found out that if you set Content handling to Convert to binary (CONVERT_TO_BINARY) the entire response has to be base64, I would otherwise get an error: Unable to base64 decode the body.

Therefore my response now looks like:

callback(null, buffer.toString('base64'));

The Integration response:

enter image description here

The Method response:

enter image description here

And Binary Media Types:

enter image description here

Solution 2:[2]

If you have a gigantic PDF, then it will take a long time for Lambda to return it and in Lambda you are billed per 100ms.

I would save it to S3 first then let the Lambda return the S3 url to the client for downloading.

Solution 3:[3]

Above solution is only for particular content-type. You can't more content type. Follow only below two-step to resolve multiple content type issue.

  1. Click on the checkbox of Use Lambda Proxy integration

API gateway --> API --> method --> integration request

enter image description here

enter image description here

  1. Create your response as

        let response = {
    
          statusCode: 200,
          headers: {
            'Content-type': 'application/pdf',//you can change any content type
            'content-disposition': 'attachment; filename=test.pdf' // key of success
          },
          body: buffer.toString('base64'),
          isBase64Encoded: true
        };
        return response;
    

Note* - It is not secure

Solution 4:[4]

I was having a similar issue where pdf where downloaded as base64 and started happening when changed the serverles.yml file from:

binaryMediaTypes:
      - '*/*'

to

binaryMediaTypes:
      - 'application/pdf'
      - '....other media types'

The issue is because the way AWS implemented this feature. From aws documentation here:

When a request contains multiple media types in its Accept header, API Gateway honors only the first Accept media type. If you can't control the order of the Accept media types and the media type of your binary content isn't the first in the list, add the first Accept media type in the binaryMediaTypes list of your API. API Gateway handles all content types in this list as binary.

Basically if the first media type contained in the accept request header is not in your list in binaryMediaTypes then you will get base64 back.

I checked the request in the browser and the first media type in the accept header was text/html so I got it working after changing my settings to:

binaryMediaTypes:
          - 'application/pdf'
          - '....other media types'
          - 'text/html'

Hope this helps anyone with the same issue.

Sources

This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.

Source: Stack Overflow

Solution Source
Solution 1 teocomi
Solution 2 Noel Llevares
Solution 3 Máté
Solution 4 Goca