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'];constAWS=require("aws-sdk");constS3=newAWS.S3({signatureVersion:"v4"});constchromium=require("chrome-aws-lambda");exports.handler=asyncfunction(event,context,callback){try{if(!event.html){callback("unable to get html");return;}constfileName=event.filename,tmpFileName=`/tmp/${Math.random().toString(36).slice(2)}.pdf`,bucket=event.bucket,pageSize=event.pageSize||"A4",html=event.html;constexecutablePath=awaitchromium.executablePath,browser=awaitchromium.puppeteer.launch({args:chromium.args,defaultViewport:chromium.defaultViewport,executablePath,headless:chromium.headless,ignoreHTTPSErrors:true});constpage=awaitbrowser.newPage();awaitpage.setContent(html);constpdf=awaitpage.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);}};