How to generate PDF from HTML on AWS Lambda

Anyone had luck in creating a function for html to pdf generation on AWS?
The closest I could get was using wkhtmltopdf and I can get the base64 of the pdf of the html string, but when I output it to the response, I can’t open the PDF.
Any good examples?

This is the code I’m using:

import wkhtmltopdf from "wkhtmltopdf";
import MemoryStream from "memorystream";

process.env['PATH'] = process.env['PATH'] + ':' + process.env['LAMBDA_TASK_ROOT'];

export async function main(event, context, callback) {
    const html = '<h1>Test</h1><p>Hello world</p>';
    const memStream = new MemoryStream();

    wkhtmltopdf(html, { pageSize: 'letter' }, function(code, signal) {
        let pdf = memStream.read();
        const response = {
            statusCode: 200,
            headers: {
                'Content-type' : 'application/pdf',
                "Access-Control-Allow-Origin": "*",
                "Access-Control-Allow-Credentials": true
            },
            body: pdf.toString('base64'),
            isBase64Encoded : true
        };
        callback(null, response);
    }).pipe(memStream);
}

And I’m also including the wkhtmltopdf binary on the root that I get from this tutorial:
https://www.drivenbycode.com/creating-pdfs-from-html-with-aws-lambda-and-api-gateway/

Thanks!

I’m not sure if this is related but if you declare your handler function async then you don’t use callback. If you’re using the Node 8.10 runtime it won’t work.

1 Like

Take a look at this https://stackoverflow.com/questions/45348580/aws-lambda-returning-pdf-file

1 Like

You might also give chromeless or serverless chrome a shot:

1 Like

Thanks for the suggestions and guidance.

My problem was that I was testing directly on the service endpoint.
As soon as I called the service from the frontend (Javascript) and open it on a new window it worked:

window.open("data:application/pdf;base64, " + pdf);

Api2Pdf runs on AWS Lambda and supports wkhtmltopdf as well as Headless Chrome. Super easy.

Checkout this post https://medium.com/@crespo.wang/how-to-generate-pdf-in-aws-lambda-c92477068cf6, it might help

There are people asking for the solution using headless chrome puppeteer, here it is https://medium.com/swlh/how-to-create-pdf-in-lambda-using-puppeteer-6355348b8a82

Does anyone has this working?

I have a piece of code that works fine when running locally, yet when I deploy this to AWS Lambda then I get an error.

Here is what I tried:

const converter = require('html-pdf');

const pdf = await new Promise(async (resolve, reject) => {
    converter.create(html).toBuffer((err, buffer) => {
        resolve(buffer);
    });
});

Once, deployed I’m getting:

Error: write EPIPE

I searched for the solution and found this SO:

The solution is apparently to add phantomPath

Therefore, I modified the code like this:

const phantomPath = path.join(ROOT_PATH, `static/phantomjs_linux-x86_64`)

converter.create(html, { phantomPath }).toBuffer((err, buffer) => {

Additionally, I downloaded and added precompiled phantomjs_linux-x86_64 to static directory that gets deployed to AWS Lambda.

Yet, that still fails with Error: write EPIPE even though the file is there and I pass phantomPath

Any help or advice?

UPDATE

I think I’ve finally found the issue - it must be the permissions! When I deploy my function and check files in static directory I see:

-rw-r--r-- 1 slicer 497 56587116 Apr  3  2020 phantomjs_linux-x86_64

I tried to change the permissions with chmod a+x phantomjs_linux-x86_64 yet I got:

Error: Command failed: chmod a+x /var/task/static/phantomjs_linux-x86_64
chmod: changing permissions of ‘/var/task/static/phantomjs_linux-x86_64’: Read-only file system

Therefore, I assumed I should be able to reproduce this on mac too and I downloaded and replaced phantomjs_linux-x86_64 with phantomjs_osx locally. Next, I removed permissions with: chmod ago-x phantomjs_osx:

-rw-r--r--   1 iaforek  staff  45020592 Apr  3 15:09 phantomjs_osx

When I ran the function locally… BOOM I was able to reproduce the same error:

Unhandled exception: write EPIPE