Generate PDFs in Spring Boot with OpenHtmlToPdf and Freemarker – Step‑by‑Step Guide
This tutorial demonstrates how to integrate OpenHtmlToPdf with a Spring Boot 3.2.8 application, using Freemarker templates and custom fonts to render HTML content and deliver high‑quality PDF files via a REST endpoint, complete with code examples and configuration details.
Overview
OpenHtmlToPdf is an open‑source Java library that converts HTML content into PDF documents, supporting most CSS styles and part of HTML5. The article shows how to use it in a Spring Boot 3.2.8 project together with the Freemarker template engine to generate PDFs on the fly.
Dependencies
<code><!-- 该库进行HTML的解析 -->
<dependency>
<groupId>org.jsoup</groupId>
<artifactId>jsoup</artifactId>
<version>1.18.1</version>
</dependency>
<!-- 将HTML内容转换为PDF文档 -->
<dependency>
<groupId>com.openhtmltopdf</groupId>
<artifactId>openhtmltopdf-core</artifactId>
<version>${openhtmltopdf.version}</version>
</dependency>
<dependency>
<groupId>com.openhtmltopdf</groupId>
<artifactId>openhtmltopdf-pdfbox</artifactId>
<version>${openhtmltopdf.version}</version>
</dependency>
</code>Template preparation
<code><html>
<head>
<meta charset="UTF-8">
<title>用户列表</title>
<style>
body {font-family: "BabelStoneHan",sans-serif;}
table {width: 100%;border-collapse: collapse;}
th,td {border: 1px solid black;padding: 8px;text-align: left;}
th {background-color: #f2f2f2;}
</style>
</head>
<body>
<div class="title-container"><h2>XXXOOO全部用户列表信息</h2></div>
<div class="content-container">
<table>
<tr>
<th>编号</th><th>姓名</th><th>性别</th><th>身份证</th><th>年龄</th><th>邮箱</th><th>头像</th>
</tr>
<#list users as user>
<tr>
<td>${user.id}</td>
<td>${user.name}</td>
<td>${user.sex}</td>
<td>${user.idNo}</td>
<td>${user.age}</td>
<td>${user.email}</td>
<td><img src="https://img0.baidu.com/it/u=3366443890,3137275928&fm=253&fmt=auto&app=120&f=JPEG?w=500&h=500" alt="Avatar"></td>
</tr>
</#list>
</table>
</div>
</body>
</html>
</code>Freemarker configuration and sample data
<code>@Bean
Configuration config(ResourceLoader loader) {
freemarker.template.Configuration cfg = null;
try {
cfg = new Configuration(Configuration.VERSION_2_3_33);
// 设置模板路径
File baseDir = loader.getResource("classpath:/templates/").getFile();
TemplateLoader templateLoader = new FileTemplateLoader(baseDir);
cfg.setTemplateLoader(templateLoader);
// 设置编码
cfg.setDefaultEncoding("UTF-8");
cfg.setTemplateExceptionHandler(TemplateExceptionHandler.RETHROW_HANDLER);
} catch (IOException e) {
e.printStackTrace();
}
return cfg;
}
private static final List<User> DATAS = new ArrayList<>();
static {
for (int i = 0; i < 10; i++) {
DATAS.add(new User(
i + 0L,
"姓名 - " + i,
new Random().nextInt(3) % 2 == 0 ? "男" : "女",
"身份证 - " + i,
new Random().nextInt(100),
i + "@qq.com",
"avatar.png" // 头像实际在模板中写死了
));
}
}
</code>PDF generation controller
<code>@RestController
@RequestMapping("/users")
public class UserController {
private final Configuration cfg;
public UserController(Configuration cfg) {
this.cfg = cfg;
}
// 生成PDF
@GetMapping("/gen")
public Object gen(HttpServletResponse response) {
// 设置文件下载 Header
String fileName = new String("用户列表.pdf".getBytes(StandardCharsets.UTF_8), StandardCharsets.ISO_8859_1);
response.setHeader("Content-Disposition", "attachment; filename=\"" + fileName + "\"");
response.setContentType("application/octet-stream");
try {
// 获取模板
Template template = this.cfg.getTemplate("users.ftl");
// 准备模板需要的数据
Map<String, Object> root = new HashMap<>();
root.put("users", DATAS);
// 生成 HTML 内容到内存中
ByteArrayOutputStream baos = new ByteArrayOutputStream();
Writer out = new OutputStreamWriter(baos);
template.process(root, out);
// 将上面生成的 HTML 内容进行解析
Document document = Jsoup.parse(baos.toString(StandardCharsets.UTF_8), "UTF-8");
document.outputSettings().syntax(Document.OutputSettings.Syntax.html);
// 构建 PDF 文档,最后将上面的 Document 进行输出
PdfRendererBuilder builder = new PdfRendererBuilder();
// 使用字体,字体名要与模板中 CSS 样式中指定的字体名相同
builder.useFont(new ClassPathResource("/fonts/BabelStoneHan.ttf").getFile(),
"BabelStoneHan", 1, BaseRendererBuilder.FontStyle.NORMAL, true);
builder.toStream(response.getOutputStream());
builder.useFastMode();
builder.withW3cDocument(new W3CDom().fromJsoup(document), new ClassPathResource("/templates/").getPath());
builder.run();
} catch (Exception e) {
e.printStackTrace();
}
return "生成成功";
}
}
</code>Conclusion
OpenHtmlToPdf is a powerful open‑source Java library designed for converting HTML content into high‑quality PDF documents. Its strong HTML/CSS compatibility, flexible configuration options, and easy integration make it suitable for generating reports, contracts, e‑books, and other PDF‑based outputs in Spring Boot applications.
Spring Full-Stack Practical Cases
Full-stack Java development with Vue 2/3 front-end suite; hands-on examples and source code analysis for Spring, Spring Boot 2/3, and Spring Cloud.
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.