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);
}
};
参考リンク