Pdfkit: PDFKit not working in AWS Lambda

Created on 17 May 2019  路  12Comments  路  Source: foliojs/pdfkit

Question

Trying to convert html text to PDF with PDFKit library in AWS Lambda function. The PDF is not generated.

Description

Trying to convert html text to PDF with PDFKit library in AWS Lambda function and storing the generated PDF in s3 bucket.

Code sample

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");
        }
   });
});

}

Your environment

  • pdfkit version:
  • Node version:8.10
  • Browser version (if applicable):
  • Operating System: AWS VM
needs info

All 12 comments

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...

Was this page helpful?
0 / 5 - 0 ratings