LoginSignup
2
0

More than 3 years have passed since last update.

Node12系 AWS LambdaでHTMLをPDFに変換しようとしたらいろいろハマった

Last updated at Posted at 2020-02-10

Node8系でwkhtmktopdfを使ってHTMLをPDFに変換するLambdaを使っていたのだが、Node8系で動いていた。
Node8系がサポートされなくなるということで、12系にそのままあげたら動かなくなってしまったのでNode12系でHTMLをPDFに変換するLambdaを作り直す必要が出てきた。

HTMLをPDFに変換するLambdaについては結構多くの記事が見つかったが、なかなか上手くいかなかった。

やりたかったこと

Lambdaで日本語を含むHTMLをPDFに変換し、S3に保存する

試したが上手くいかなかった方法

  • wkhtmlpdf
    • 自分が見つけられなかっただけかもしれないが、Node12系でも問題なく動くソースを見つけられなかった
  • html-pdf
    • phantomjsの128エラーでちっとも動かなかった
  • puppeteer
    • 動きそうな気配はあったが、node_modulesのサイズが大きすぎてLambdaの最大ソースサイズをオーバーしてしまった

上手く行った方法

使用モジュール

chrome-aws-lambda を使った。
puppeteer-coreもnpm installする必要があるが、puppeteerだと大きすぎるから必要なcoreだけ使ってるっぽい。

注意点

  • Lambdaのメモリ設定を512MBにする必要があった
    • 最初256MBにしていて、browserがlaunchできなかったいうようなエラーが出て、chrome-aws-lambdaもダメかあと思っていたところBUG報告で512MBにしたらできたで、って書いてあった
  • .fontsをちゃんとzipファイルに含める
    • Lambda環境に日本語フォントはない。自分で.fontsとして読み込ませる必要があるが、日本語が反映されへんな〜と思ったら.fontsをzipファイルに含むのが漏れていたというオチだった

コード

構造

┣ pdfGenerator.js
┣ package.json
┣ package-lock.json
┣ .fonts
  ┣ ipaexg.ttf
  ┣ ipaexm.ttf

コード

pdfGenerator.js
/* Lambda環境でも日本語フォントを使えるようにするには.fontsを読み込ませるためにHOMEを設定する必要ある */
process.env['HOME'] = "/var/task";
process.env['PATH'] = process.env['PATH'] + ':' + process.env['LAMBDA_TASK_ROOT'];

const AWS = require("aws-sdk");
const S3 = new AWS.S3({ signatureVersion: "v4" });
const chromium = require("chrome-aws-lambda");

exports.handler = async function(event, context, callback) {
    try {
        if (!event.html) {
            callback("unable to get html");
            return;
        }

        const fileName = event.filename,
            tmpFileName = `/tmp/${Math.random().toString(36).slice(2)}.pdf`,
            bucket =  event.bucket,
            pageSize = event.pageSize || "A4",
            html = event.html;

        const executablePath = await chromium.executablePath,
            browser = await chromium.puppeteer.launch({
                args: chromium.args,
                defaultViewport: chromium.defaultViewport,
                executablePath,
                headless: chromium.headless,
                ignoreHTTPSErrors: true
            });

        const page = await browser.newPage();
        await page.setContent(html);
        const pdf = await page.pdf({
            path: tmpFileName,
            format: pageSize
        });

        browser.close();

        S3.putObject({
            Bucket: bucket,
            Key: fileName,
            Body: pdf,
            ContentType: "application/pdf"
        }, (error) => {
            callback(error);
        });
    } catch(e) {
        callback(e);
    }
};

参考リンク

2
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
2
0