Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

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});
});
like image 204
Padawan Avatar asked Feb 17 '26 23:02

Padawan


1 Answers

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.

like image 68
adamkonrad Avatar answered Feb 20 '26 19:02

adamkonrad



Donate For Us

If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!