3

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});
});
Padawan
  • 770
  • 1
  • 8
  • 18

2 Answers2

2

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.

adamkonrad
  • 6,794
  • 1
  • 34
  • 41
  • Great suggestion and I believe this would work, however storage does not fit into the requirements at this time. I hope this helps others! – Padawan Jul 09 '17 at 22:06
1

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.

Bob Kinney
  • 8,870
  • 1
  • 27
  • 35
  • Thanks for the suggestion! Unfortunately I did not have success going this route but it give me some experience with response mapping templates. – Padawan Jul 09 '17 at 22:04