Padawan
Padawan

Reputation: 820

API Gateway Response Download File using Node, PDFMake, Serverless

I am in the process of migrating my NodeJS project to API Gateway and I cannot figure out how to download a file from Lambda.

Here is a snippet of the response code on my local Node project.

app.get('/downloadPDF', function (req, res) {
  res.setHeader('Content-disposition', 'attachment; filename=test.pdf');
  res.setHeader('Content-type', 'application/pdf');
  var PdfPrinter = require('pdfmake');
  var printer = new PdfPrinter(fonts);

  var pdfDoc = printer.createPdfKitDocument(dd);
  pdfDoc.pipe(res);
  pdfDoc.end();
});

Piping to the response I was able to get back a PDF.

Here is a snippet of my lambda function using serverless.

module.exports.createPDF = (event, context) => {
  var PdfPrinter = require('pdfmake');
  var printer = new PdfPrinter(fonts);

  var pdfDoc = printer.createPdfKitDocument(dd);
  pdfDoc.pipe(res);
  pdfDoc.end();
}

Here is the endpoint in my serverless.yml

createPDF:
handler: functions.myFunction
events:
  - http:
      path: services/getPDF
      method: get
      response:
        headers:
          Content-Type: "'application/pdf'"
          Content-disposition: "'attachment; filename=test.pdf'"

I don't know how to get reference to the response object in Lambda to pipe to. Is that possible? Is there another way?


Update

I ended up solving this issue by returning the base64 encoded PDF binary in a JSON response and decoding on the client. Note: using the base64 decoding in the response mapping template did not work.

Sample code:

    var buffers = [];
pdfDoc.on('data', buffers.push.bind(buffers));

pdfDoc.on('end', function () {
    var bufCat = Buffer.concat(buffers);

    var pdfBase64 = bufCat.toString('base64');

return cb(null, 
    {"statusCode": 200,
    "headers": {"Content-Type": "application/json"},
    "body": pdfBase64});
});

Upvotes: 3

Views: 4745

Answers (2)

adamkonrad
adamkonrad

Reputation: 7122

API Gateway doesn't support sending binary responses. As an alternative, you can have your Lambda store binary data in S3 and return HTTP redirect to the S3 object location via the Location header.

Upvotes: 2

Bob Kinney
Bob Kinney

Reputation: 9020

API Gateway does not natively support binary data. Some of our customers have had success base64 encoding the data in Lambda, including in a JSON reponse and using response mapping template to decode the data to respond to the client.

Upvotes: 1

Related Questions