Generate PDFs in Java with iText: From Hello World to Dynamic Templates

This tutorial explains how to generate PDF files in Java using the iText library, covering dependency setup, a simple "Hello World" PDF example, converting complex HTML pages to PDF, and dynamic content insertion with Freemarker templates.

macrozheng
macrozheng
macrozheng
Generate PDFs in Java with iText: From Hello World to Dynamic Templates

Background Introduction

In many business scenarios developers need to provide electronic documents such as e‑invoices, order receipts, or signed contracts for users to view, print, or download. The most common solution is to generate a PDF from the relevant data and return it to the client.

Solution Practice

The core library used in this article is iText, an open‑source Java library that can create PDF, RTF, and convert XML/HTML to PDF. iText has two major versions, iText5 (widely used) and iText7 (the newer rewrite), but for simple use cases either version works.

1. Add iText Dependency

<dependencies>
    <!-- pdf:start -->
    <dependency>
        <groupId>com.itextpdf</groupId>
        <artifactId>itextpdf</artifactId>
        <version>5.5.11</version>
    </dependency>
    <dependency>
        <groupId>com.itextpdf.tool</groupId>
        <artifactId>xmlworker</artifactId>
        <version>5.5.11</version>
    </dependency>
    <!-- Support Chinese characters -->
    <dependency>
        <groupId>com.itextpdf</groupId>
        <artifactId>itext-asian</artifactId>
        <version>5.2.0</version>
    </dependency>
    <!-- CSS rendering support -->
    <dependency>
        <groupId>org.xhtmlrenderer</groupId>
        <artifactId>flying-saucer-pdf-itext5</artifactId>
        <version>9.1.16</version>
    </dependency>
    <!-- Convert HTML to XHTML -->
    <dependency>
        <groupId>net.sf.jtidy</groupId>
        <artifactId>jtidy</artifactId>
        <version>r938</version>
    </dependency>
    <!-- pdf:end -->
</dependencies>

2. Simple Implementation

A basic "Hello World" PDF can be created with the following code:

public class CreatePDFMainTest {
    public static void main(String[] args) throws Exception {
        Document document = new Document(PageSize.A4);
        // Create writer instance
        PdfWriter.getInstance(document, new FileOutputStream("hello.pdf"));
        // Create Chinese font (optional)
        BaseFont bfChinese = BaseFont.createFont("STSong-Light", "UniGB-UCS2-H", BaseFont.NOT_EMBEDDED);
        Font fontChinese = new Font(bfChinese, 12, Font.NORMAL);
        document.open();
        Paragraph paragraph = new Paragraph("hello world", fontChinese);
        document.add(paragraph);
        document.close();
    }
}

Running the program produces hello.pdf containing the text "hello world".

3. Complex Implementation – HTML to PDF

For more complex documents it is convenient to write the content as an HTML page and let iText convert it to PDF. First, create an HTML file (e.g., printDemo.html) that contains the layout of the document.

<html>
<head></head>
<body>
    <meta http-equiv="Content-Type" content="text/html; charset=UTF-8" />
    <title>入库单</title>
    <div>
        <table width="100%" border="0" cellspacing="0" cellpadding="0">
            <tr>
                <td height="40" colspan="2"><h3 style="font-weight: bold; text-align: center; font-size: 24px;">入库单</h3></td>
            </tr>
            ... (table rows omitted for brevity) ...
        </table>
    </div>
</body>
</html>

The Java code that reads the HTML file and converts it to PDF is shown below:

public class CreatePDFMainTest {
    private static void writeToOutputStreamAsPDF(String htmlStr) throws Exception {
        String targetFile = "pdfDemo.pdf";
        Document document = new Document(PageSize.A4, 25, 25, 15, 40);
        PdfWriter writer = PdfWriter.getInstance(document, new FileOutputStream(targetFile));
        // Optional header/footer
        PdfReportHeaderFooter header = new PdfReportHeaderFooter("", 8, PageSize.A4);
        writer.setPageEvent(header);
        writer.addViewerPreference(PdfName.PRINTSCALING, PdfName.NONE);
        document.open();
        // CSS resolver
        CSSResolver cssResolver = new StyleAttrCSSResolver();
        CssAppliers cssAppliers = new CssAppliersImpl(new XMLWorkerFontProvider(){
            @Override
            public Font getFont(String fontname, String encoding, boolean embedded, float size, int style, BaseColor color) {
                try {
                    BaseFont bfChinese = BaseFont.createFont("STSongStd-Light", "UniGB-UCS2-H", BaseFont.NOT_EMBEDDED);
                    return new Font(bfChinese, size, style);
                } catch (Exception e) {
                    return super.getFont(fontname, encoding, size, style);
                }
            }
        });
        HtmlPipelineContext htmlContext = new HtmlPipelineContext(cssAppliers);
        htmlContext.setTagFactory(Tags.getHtmlTagProcessorFactory());
        htmlContext.setImageProvider(new AbstractImageProvider(){
            @Override
            public Image retrieve(String src) {
                int pos = src.indexOf("base64,");
                try {
                    if (src.startsWith("data") && pos > 0) {
                        byte[] img = Base64.decode(src.substring(pos + 7));
                        return Image.getInstance(img);
                    } else if (src.startsWith("http")) {
                        return Image.getInstance(src);
                    }
                } catch (Exception e) {
                    return null;
                }
                return null;
            }
            @Override
            public String getImageRootPath() { return null; }
        });
        PdfWriterPipeline pdf = new PdfWriterPipeline(document, writer);
        HtmlPipeline html = new HtmlPipeline(htmlContext, pdf);
        CssResolverPipeline css = new CssResolverPipeline(cssResolver, html);
        XMLWorker worker = new XMLWorker(css, true);
        XMLParser parser = new XMLParser(worker);
        parser.parse(new ByteArrayInputStream(htmlStr.getBytes()));
        document.close();
    }
    private static String readHtmlFile() {
        StringBuilder sb = new StringBuilder();
        try {
            BufferedReader reader = new BufferedReader(new FileReader("printDemo.html"));
            String line;
            while ((line = reader.readLine()) != null) {
                sb.append(line);
            }
            reader.close();
        } catch (IOException e) {
            return null;
        }
        return sb.toString();
    }
    public static void main(String[] args) throws Exception {
        String htmlStr = readHtmlFile();
        writeToOutputStreamAsPDF(htmlStr);
    }
}

Executing the program generates pdfDemo.pdf, which contains the rendered HTML table and images.

4. Variable Replacement

When the HTML content is dynamic, you can use a template engine such as Freemarker to replace placeholders (e.g., ${name}) before converting the HTML to PDF.

<html>
<head><meta charset="utf-8"/><title></title></head>
<body>
    <div>您好:${name}</div>
    <div>欢迎,登录博客网站</div>
</body>
</html>

Conclusion

The iText framework is a practical solution for generating PDF files in Java, especially for simple documents. For more complex PDFs you may need to perform additional customizations, and the official iText API provides extensive capabilities for advanced scenarios.

Original Source

Signed-in readers can open the original source through BestHub's protected redirect.

Sign in to view source
Republication Notice

This article has been distilled and summarized from source material, then republished for learning and reference. If you believe it infringes your rights, please contactadmin@besthub.devand we will review it promptly.

Backend DevelopmentiTextpdf-generationFreemarkerHTML to PDF
macrozheng
Written by

macrozheng

Dedicated to Java tech sharing and dissecting top open-source projects. Topics include Spring Boot, Spring Cloud, Docker, Kubernetes and more. Author’s GitHub project “mall” has 50K+ stars.

0 followers
Reader feedback

How this landed with the community

Sign in to like

Rate this article

Was this worth your time?

Sign in to rate
Discussion

0 Comments

Thoughtful readers leave field notes, pushback, and hard-won operational detail here.