Trying to convert html text to PDF with PDFKit library in AWS Lambda function. The PDF is not generated.
Trying to convert html text to PDF with PDFKit library in AWS Lambda function and storing the generated PDF in s3 bucket.
exports.handler = async (event) => {
let doc = new PDFDocument();
var s3 = new AWS.S3();
let fileCreate = fs.createWriteStream("/tmp/pdfgen.pdf");
doc.pipe(fileCreate);
doc.addPage()
.fontSize(25)
.text('Here is some vector graphics...', 100, 100);
// # Finalize PDF file
doc.end();
// Send pdf file to s3
fileCreate.on('finish', function () {
//get the file size
const stats = fs.statSync("/tmp/" + fileName);
s3.putObject({
Bucket: [bucketName],
Key: fileName,
Body: fs.createReadStream("/tmp/" + fileName),
ContentType: "application/pdf",
ContentLength: stats.size,
}, function (err) {
if (err) {
console.log(err, err.stack);
callback(err);
} else {
console.log("Done");
callback(null, "done");
}
});
});
}
any error message?
the 'finish' even is run?
No error messages. No logs displayed inside finish
You can try https://github.com/foliojs/pdfkit/issues/265#issuecomment-246564718
or in worst case create the file yourself using something like in the test: https://github.com/foliojs/pdfkit/blob/master/tests/integration/helpers.js#L70-L77
@balaji668 What tool are you using to package and deploy your lambda function? Also, what are you execution parameters?
There's several tools available, and they, combined with your function configuration, could have an impact on how your function & PDFKit will run.
If you could provide a gist or a sample repo to test with, I can try it out in my AWS account and see if I can reproduce your issue.
Just a get method to execute in the index handler. using function code as upload zip ( to package NodeJS modules and the index files) in Lambda functions.
@balaji668 please try the code below and report back
function savePdfToFile(pdf, fileName) {
return new Promise((resolve, reject) => {
// To determine when the PDF has finished being written successfully
// we need to confirm the following 2 conditions:
//
// 1. The write stream has been closed
// 2. PDFDocument.end() was called syncronously without an error being thrown
let pendingStepCount = 2;
const stepFinished = () => {
if (--pendingStepCount == 0) {
resolve();
}
};
const writeStream = fs.createWriteStream(fileName);
writeStream.on('close', stepFinished);
pdf.pipe(writeStream);
pdf.end();
stepFinished();
});
}
exports.handler = async (event) => {
let doc = new PDFDocument();
var s3 = new AWS.S3();
doc.addPage()
.fontSize(25)
.text('Here is some vector graphics...', 100, 100);
// # Finalize PDF file
await savePdfToFile(doc, "/tmp/pdfgen.pdf");
// Send pdf file to s3
//get the file size
const stats = fs.statSync("/tmp/pdfgen.pdf");
s3.putObject({
Bucket: [bucketName],
Key: fileName,
Body: fs.createReadStream("/tmp/" + fileName),
ContentType: "application/pdf",
ContentLength: stats.size,
}, function (err) {
if (err) {
console.log(err, err.stack);
} else {
console.log("Done");
}
});
};
@balaji668 can you try the code above to see if works?
Thanks above code works. Permission issue for Lambda function in accessing the s3 bucket.
Also there is issue in rendering html code. Its displayed as html tags. Working on it with
@balaji668 please try the code below and report back
function savePdfToFile(pdf, fileName) { return new Promise((resolve, reject) => { // To determine when the PDF has finished being written successfully // we need to confirm the following 2 conditions: // // 1. The write stream has been closed // 2. PDFDocument.end() was called syncronously without an error being thrown let pendingStepCount = 2; const stepFinished = () => { if (--pendingStepCount == 0) { resolve(); } }; const writeStream = fs.createWriteStream(fileName); writeStream.on('close', stepFinished); pdf.pipe(writeStream); pdf.end(); stepFinished(); }); } exports.handler = async (event) => { let doc = new PDFDocument(); var s3 = new AWS.S3(); doc.addPage() .fontSize(25) .text('Here is some vector graphics...', 100, 100); // # Finalize PDF file await savePdfToFile(doc, "/tmp/pdfgen.pdf"); // Send pdf file to s3 //get the file size const stats = fs.statSync("/tmp/pdfgen.pdf"); s3.putObject({ Bucket: [bucketName], Key: fileName, Body: fs.createReadStream("/tmp/" + fileName), ContentType: "application/pdf", ContentLength: stats.size, }, function (err) { if (err) { console.log(err, err.stack); } else { console.log("Done"); } }); };
this is not working
To be more specific, it can get a PDF generated but always being an empty pdf frame.
(without any content you write into it, the pdf can be opened but showing 1 empty page)
if you try to embed image / font into it, the file gets bigger too, but seems not working also.
Extracting with pdfimages gives :
Syntax Error (713764): Bad FCHECK in flate stream
Syntax Error: Embedded font file may be invalid
Syntax Error (712927): Bad FCHECK in flate stream
Syntax Error (711999): Bad FCHECK in flate stream
The file can still be opened by a pdf reader showing 1 empty page
I've got it working using Serverless framework
See https://medium.com/@crespo.wang/create-pdf-using-pdfkit-on-serverless-aws-lambda-with-layer-721ca86724b2
@crespowang Can you show how to upload to s3 instead of sending response? I have been trying to do this all day...