はじめに
現在プロジェクトでSpring(Java)を使用しているのですが、PDF出力機能が要件にあり、1日ほどハマってしまったので
備忘録がてら記事にしました。JavaでPDF出力するにあたって、商用利用可能であること、form操作ができること、メジャーなライブラリであることを
条件に探していたところPDFBox(バージョン2.0.22)というApache License 2.0のライブラリが見つかったので今回はそちらを採用しました。
また今回のPDF出力機能は、白紙の状態から文字をPDF出力するものではなく、決まったPDFテンプレートがあり、それらに対して、
データをマッピングして出力する要件でした。
何が起きたか?
白紙の状態からPDF出力するなら日本語の記事がたくさんあるのですが、今回のように
テンプレートを読み込んでそこから日本語出力するという記事や公式ドキュメントが中々見つからず苦労しました。
白紙からの出力ならここで丁寧に解説されていますので参考にしてみて下さい。
https://weblabo.oscasierra.net/java-pdfbox-1/
まず前提として使用するPDFテンプレートはAdobe Acrobatなどでフォームが作られているものとします。
そのフォームを読み取ってデータをマッピングするには、以下のようにコードを記述する必要があります。
// 読み込むPDFテンプレートを指定
PDDocument pdfDocument = PDDocument.load(new File("sample.pdf")
// ドキュメントカタログを取得
PDDocumentCatalog docCatalog = pdfDocument.getDocumentCatalog();
PDAcroForm acroForm = docCatalog.getAcroForm();
acroForm.setNeedAppearances(true);
acroForm.setXFA(null);
pdfDocument.getDocumentCatalog().setAcroForm(acroForm);
// 商用利用可能な日本語フォントを設定
// 拡張子otfは、サポートされてないみたいで動作しませんでしたので、拡張子はttfのフォントを推奨します。
PDFont font = PDType0Font.load(pdfDocument, new File("mplus-1p-regular.ttf"));
// PDFに出力する文字が日本語だとこの設定が必要
PDResources res = new PDResources();
COSName fontName = res.add(font);
acroForm.setDefaultResources(res);
acroForm.setDefaultAppearance('/' + fontName.getName() + " 10 Tf 0 g");
// 実際のPDFページ
// acroForm.getField("オブジェクト名")にAdobe Acrobatなどで、セットされているオブジェクト名を指定。
// field.setValueで値をセット。
// field.setReadOnly(true);で動的なフォームを読み込み専用に変換。
PDTextField field = (PDTextField) acroForm.getField("sample_field");
field.setValue("ここの文字が対象のfieldに出力されるよ!!");
field.setReadOnly(true);
// フロント側で描画するため、バイト配列で返却
ByteArrayOutputStream byteArrayOutputStream = new ByteArrayOutputStream();
pdfDocument.save(byteArrayOutputStream);
pdfDocument.close();
return byteArrayOutputStream.toByteArray();
まとめ
英語かつ情報が古かったので隅から隅まで徹底的に調査しました。
スタックオーバーフローや英語のドキュメント、公式ドキュメントなど。。。
本来であれば一時情報である公式ドキュメントで解決したかったのですが、
情報が少なすぎました。。
特にこの箇所↓
// PDFに出力する文字が日本語だとこの設定が必要
PDResources res = new PDResources();
COSName fontName = res.add(font);
acroForm.setDefaultResources(res);
acroForm.setDefaultAppearance('/' + fontName.getName() + " 10 Tf 0 g");
英語はエンジニアにとって必須だなぁと痛感した出来事でもありました。
また、僕も誰かの記事を見て救われたので、僕の誰かに役立つことを願って書き記します笑
最後まで見ていただきありがとうございます〜。LGTMよろしくです!
使用したフォント
https://fonts.google.com/specimen/M+PLUS+1p?subset=japanese
使用したライブラリ(バージョンは2.0.22を使用)
https://pdfbox.apache.org/
参考記事
https://qiita.com/ota-meshi/items/55a6c379544b33728b58
https://weblabo.oscasierra.net/java-pdfbox-1/