1. 概要

このクイックチュートリアルでは、 JavaでOpenPDFを使用して、プログラムでHTMLファイルをPDF形式に変換する方法を見ていきます

2. OpenPDF

OpenPDFは、LGPLおよびMPLライセンスの下でPDFファイルを作成および編集するための無料のJavaライブラリです。 これはiTextプログラムのフォークです。 実際、バージョン5より前では、OpenPDFを使用してPDFを生成するためのコードはiTextAPIとほぼ同じでした。 これは、JavaでPDFを作成するための手入れの行き届いたソリューションです。

3. フライングソーサーを使用した変換

Flying Saucerは、スタイルとフォーマットのためにCSS 2.1を使用して整形式のXML(またはXHTML)をレンダリングし、PDF、画像、およびスイングパネルへの出力を生成できるようにするJavaライブラリです。

3.1. Mavenの依存関係

Mavenの依存関係から始めましょう:

<dependency>
    <groupId>org.jsoup</groupId>
    <artifactId>jsoup</artifactId>
    <version>1.13.1</version>
</dependency>
<dependency>
    <groupId>org.xhtmlrenderer</groupId>
    <artifactId>flying-saucer-pdf-openpdf</artifactId>
    <version>9.1.20</version>
</dependency>

ライブラリjsoupを使用して、HTMLファイル、入力ストリーム、URL、さらには文字列を解析します。 DOM(Document Object Model)トラバーサル機能、CSS、およびHTMLからデータを抽出するためのjQueryのようなセレクターを提供します。

flying-saucer-pdf-openpdf ライブラリは、入力としてHTMLファイルのXML表現を受け入れ、CSSフォーマットとスタイル設定を適用し、PDFを出力します。

3.2. HTMLからPDFへ

このチュートリアルでは、Flying SaucerとOpenPDFを使用して、HTMLの画像やスタイリングなど、HTMLからPDFへの変換で発生する可能性のある単純なインスタンスについて説明します。 また、外部のスタイル、画像、フォントを受け入れるようにコードをカスタマイズする方法についても説明します。

サンプルのHTMLコードを見てみましょう。

<html>
    <head>
        <style>
            .center_div {
                border: 1px solid gray;
                margin-left: auto;
                margin-right: auto;
                width: 90%;
                background-color: #d0f0f6;
                text-align: left;
                padding: 8px;
            }
        </style>
        <link href="style.css" rel="stylesheet">
    </head>
    <body>
        <div class="center_div">
            <h1>Hello Baeldung!</h1>
            <img src="Java_logo.png">
            <div class="myclass">
                <p>This is the tutorial to convert html to pdf.</p>
            </div>
        </div>
    </body>
</html>

HTMLをPDFに変換するには、最初に定義された場所からHTMLファイルを読み取ります。

File inputHTML = new File(HTML);

次のステップとして、jsoupを使用して上記のHTMLファイルをjsoup Documentに変換してXHTMLをレンダリングします。

以下にXHTML出力を示します。

Document document = Jsoup.parse(inputHTML, "UTF-8");
document.outputSettings().syntax(Document.OutputSettings.Syntax.xml);
return document;

最後のステップとして、前のステップで生成したXHTMLドキュメントからPDFを作成しましょう。 ITextRenderer は、このXHTMLドキュメントを取得し、出力PDFファイルを作成します。 出力ストリームが確実に閉じられるように、コードをtry-with-resourcesブロックでラップしていることに注意してください

try (OutputStream outputStream = new FileOutputStream(outputPdf)) {
    ITextRenderer renderer = new ITextRenderer();
    SharedContext sharedContext = renderer.getSharedContext();
    sharedContext.setPrint(true);
    sharedContext.setInteractive(false);
    renderer.setDocumentFromString(xhtml.html());
    renderer.layout();
    renderer.createPDF(outputStream);
}

3.3. 外部スタイリングのカスタマイズ

HTML入力ドキュメントで使用される追加のフォントをITextRendererに登録して、PDFの生成中にそれらを含めることができます。

renderer.getFontResolver().addFont(getClass().getClassLoader().getResource("fonts/PRISTINA.ttf").toString(), true);

ITextRenderer は、外部スタイルにアクセスするための相対URLを登録するために必要になる場合があります。

String baseUrl = FileSystems.getDefault()
  .getPath("src/main/resources/")
  .toUri().toURL().toString();
renderer.setDocumentFromString(xhtml, baseUrl);

ReplacedElementFactory を実装することで、画像関連の属性をカスタマイズできます

public ReplacedElement createReplacedElement(LayoutContext lc, BlockBox box, UserAgentCallback uac, int cssWidth, int cssHeight) {
    Element e = box.getElement();
    String nodeName = e.getNodeName();
    if (nodeName.equals("img")) {
        String imagePath = e.getAttribute("src");
        try {
            InputStream input = new FileInputStream("src/main/resources/"+imagePath);
            byte[] bytes = IOUtils.toByteArray(input);
            Image image = Image.getInstance(bytes);
            FSImage fsImage = new ITextFSImage(image);
            if (cssWidth != -1 || cssHeight != -1) {
                fsImage.scale(cssWidth, cssHeight);
            } else {
                fsImage.scale(2000, 1000);
            }
            return new ITextImageElement(fsImage);
        } catch (Exception e1) {
            e1.printStackTrace();
        }
    }
    return null;
}

注:上記のコードは、ベースパスの前に画像パスを付加し、提供されていない場合に備えてデフォルトの画像サイズを設定します。

次に、カスタム ReplacedElementFactorySharedContextに追加できます。

sharedContext.setReplacedElementFactory(new CustomElementFactoryImpl());

4. オープンHTMLを使用した変換

Open HTML to PDFは、レイアウトとフォーマットにCSS 2.1(およびそれ以降の標準)を使用して、整形式のXML / XHTML(および一部のHTML5)をPDFまたは画像に出力するJavaライブラリです。

4.1. Mavenの依存関係

上記のjsoupライブラリに加えて、pom.xmlファイルにいくつかのOpenHTMLtoPDFライブラリを追加する必要があります。

<dependency>
    <groupId>com.openhtmltopdf</groupId>
    <artifactId>openhtmltopdf-core</artifactId>
    <version>1.0.6</version>
</dependency>
<dependency>
    <groupId>com.openhtmltopdf</groupId>
    <artifactId>openhtmltopdf-pdfbox</artifactId>
    <version>1.0.6</version>
</dependency>

Libraryopenhtmltopdf-coreは整形式のXML/XHTMLをレンダリングし、openhtmltopdf-pdfboxはXHTMLのレンダリングされた表現からPDFドキュメントを生成します。

4.2. HTMLからPDFへ

このプログラムでは、Open HTMLを使用してHTMLをPDFに変換するために、セクション3.2で説明したのと同じHTMLを使用します。 前の例で示したように、最初にHTMLファイルを jsoup Documentに変換します。

最後のステップで、XHTMLドキュメントからPDFを作成するために、 PdfRendererBuilderはこのXHTMLドキュメントを取得し、出力ファイルとしてPDFを作成します。 ここでも、 try-with-resources を使用してロジックをラップしています:

try (OutputStream os = new FileOutputStream(outputPdf)) {
    PdfRendererBuilder builder = new PdfRendererBuilder();
    builder.withUri(outputPdf);
    builder.toStream(os);
    builder.withW3cDocument(new W3CDom().fromJsoup(doc), "/");
    builder.run();
}

4.3. 外部スタイリングのカスタマイズ

HTML入力ドキュメントで使用される追加のフォントをPdfRendererBuilderに登録して、PDFに含めることができます。

builder.useFont(new File(getClass().getClassLoader().getResource("fonts/PRISTINA.ttf").getFile()), "PRISTINA");

PdfRendererBuilder ライブラリは、前の例と同様に、外部スタイルにアクセスするための相対URLを登録するためにも必要になる場合があります。

String baseUrl = FileSystems.getDefault()
  .getPath("src/main/resources/")
  .toUri().toURL().toString();
builder.withW3cDocument(new W3CDom().fromJsoup(doc), baseUrl);

5. 結論

この記事では、FlyingSaucerとOpenHTMLを使用してHTMLをPDFに変換する方法を学びました。 また、外部フォント、スタイル、およびカスタマイズを登録する方法についても説明しました。

カスタムと同様に、このチュートリアルで使用されるすべてのコードサンプルは、GitHubから入手できます。