2019/05/28
Apache PDFBoxを実際に使用するにあたってのTIPS
目次
こんにちは、アーキテクトのQZ西垣です。
令和最初の開発者ブログです。
今回はApache PDFBoxを実際に運用中のシステムに組み込むにあたって得た知見をTIPSとして公開します。
少ないですけどね。
Apache PDFBoxとは
Apache PDFBox(以下PDFBox)とは、JavaでPDFファイルを扱うためのライブラリです。
PDFファイルを作成するために必要な一通りの機能が実装されています。
元々弊社では別のライブラリであるiTextを使用していたのですが、バージョン5から商用利用する場合有償となったため、PDFBoxに変更したという経緯があります。
ググってみたけれど
PDFBoxを使用するにあたりWebでいろいろググってみると、個々の機能については詳細な情報が見つかります。
しかしそれらは断片的で、実際にPDFファイルを生成するコードを完成させるまでには結構四苦八苦しました。
では、以下から実際にPDFファイルを作成するためのノウハウを紹介します。
なお、フレームワークとしてSpring Frameworkを使用する前提とします。
フォントの読込にはResourceLoaderを使用する
いきなり脱線します。
PDFBoxを使用するためには、まずフォントファイルが必要です。
プロジェクト内にフォントファイルを配置する必要がありますが、どこに配置すればいいのか、どうやって読み取ればいいのか、そこからつまづきました。
いろいろ調べた結果、 org.springframework.core.io.ResourceLoader
をインジェクションして使用すればいいということが判明しました。
1 2 3 4 5 6 7 8 9 10 11 12 13 |
@Component public class PdfSample1 { @Autowired private ResourceLoader resourceLoader; public void invoke() { Resource fontResource = resourceLoader.getResource(“classpath:font/font.ttf”); PDDocument document = new PDDocument(); PDFont font = PDType0Font.load(document, fontResource.getFile()); } } |
PDPageContentStream
の生成は1ページにつき1回
複数のテキストをPDFに出力するテストをしていたのですが、1つしか出力されない現象が発生していました。
テキストをPDFに出力するたびに PDPageContentStream
を生成していたのですが、それが間違いでした。
PDPageContentStream
は、1ページにつき1回だけ生成するものです。
PDPageContentStream
は close
しないと例外が発生する
自動で改ページする処理を作り込んだのですが、例外が発生していました。
何のことはない、改ページする際、元のページのために生成した PDPageContentStream
を close
していないだけでした。
座標系はページの左下が (0, 0)
わりと混乱するのが座標系です。
左下が (0, 0)
であるため、ページの高さとフォントサイズから逆算してy座標を決定する必要があります。
1 2 3 4 5 6 7 8 9 |
@Component public class PdfSample2 { public static void showText(PDPageContentStream stream, String text) { stream.newLineAtOffset(0, 0); // ページの左下に座標をセット stream.showText(text); // ページの左下にテキストを出力 } } |
ページの座標範囲外にテキスト等を出力してもエラーにならない
出力したはずのテキスト等が表示されない場合、座標も疑ってみてください。
テキストを右寄せで出力する機能はない
テキストの幅を測るメソッドがあるので、そこから逆算してx座標を決定する必要があります。
1 2 3 4 5 6 7 8 9 10 11 12 |
@Component public class PdfSample3 { // ページの幅は出力する用紙のサイズにより異なる public static void showText(PDPageContentStream stream, float pageWidth, PDFont font, float fontSize, String text) { float textWidth = font.getStringWidth(text) * fontSize / 1000f; // テキストの横幅を算出 float x = pageWidth - textWidth; stream.newLineAtOffset(x, 0); stream.showText(text); } } |
まとめ
PDFBoxについては、まだ自分もその全機能を使用したわけではありませんが、必要な機能は網羅されている感があります。
また、最初はTIPSに挙げた例のように苦労はしましたが、分かってしまえばシンプルで使いやすいライブラリでもあります。
みなさんもPDFBoxのTIPSがあれば是非教えてください。