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.
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.
Signed-in readers can open the original source through BestHub's protected redirect.
This article has been distilled and summarized from source material, then republished for learning and reference. If you believe it infringes your rights, please contactand we will review it promptly.
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.
How this landed with the community
Was this worth your time?
0 Comments
Thoughtful readers leave field notes, pushback, and hard-won operational detail here.
