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});
});
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.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With