Spring Boot Convert Html to Pdf By Freemarker Template
Overview
之前有一个需求,需要生成 pdf 报告文件,采用 html 转 pdf 可以很好的保证样式,本文记录下采用 freemarker 动态模板生成 html,然后转成 pdf 的方式
Maven Dependencies
在 pom.xml 文件中添加以下依赖
xml
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-freemarker</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<!-- Flying Saucer dependencies for HTML to PDF conversion -->
<dependency>
<groupId>org.xhtmlrenderer</groupId>
<artifactId>flying-saucer-core</artifactId>
<version>9.1.22</version>
</dependency>
<dependency>
<groupId>org.xhtmlrenderer</groupId>
<artifactId>flying-saucer-pdf-openpdf</artifactId>
<version>9.1.22</version>
</dependency>
</dependencies>
Define Freemarker Template
在 resources 下面新建目录 templates, 然后创建 template.ftl 文件
html
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8" />
<title>PDF Example</title>
<style>
h1 {
text-align: center;
color: cadetblue;
}
</style>
</head>
<body>
<h1>${title}</h1>
<p>${content}</p>
</body>
</html>
Define Service
创建一个服务类,用于渲染 Freemarker 模板并将 HTML 转换为 PDF:
java
public interface PdfGenerator {
byte[] generator(String templateName, Map<String,Object> data) throws Exception;
}
java
@Service
public class FreeMarkerPdf implements PdfGenerator{
private final Configuration freemarkerConfig;
public FreeMarkerPdf(Configuration freemarkerConfig) {
this.freemarkerConfig = freemarkerConfig;
}
@Override
public byte[] generator(String templateName, Map<String, Object> data) throws Exception {
Template template = freemarkerConfig.getTemplate("template.ftl","UTF-8");
String html = FreeMarkerTemplateUtils.processTemplateIntoString(template, data);
try (ByteArrayOutputStream outputStream = new ByteArrayOutputStream()){
ITextRenderer renderer = new ITextRenderer();
renderer.setDocumentFromString(html);
renderer.layout();
renderer.createPDF(outputStream);
return outputStream.toByteArray();
}
}
}
Define Controller
创建一个控制器,用于处理生成 PDF 的请求的测试接口:
java
@RequestMapping("pdf")
@RestController
public class TestController {
private final PdfGenerator pdfGenerator;
public TestController(PdfGenerator pdfGenerator) {
this.pdfGenerator = pdfGenerator;
}
@GetMapping
public void pdf(HttpServletResponse response,@RequestParam String title,@RequestParam String content) throws Exception {
Map<String, Object> data = new HashMap<>();
data.put("title", title);
data.put("content", content);
byte[] bytes = pdfGenerator.generator("template,ftl", data);
response.setContentType("application/pdf");
response.setHeader("Content-Disposition", "attachment; filename=generated.pdf");
response.setContentLength(bytes.length);
try (OutputStream os = response.getOutputStream()) {
os.write(bytes);
}
}
}
Test
浏览中输入 http://127.0.0.1:8080/pdf?title=test&content=hello 可以看到可以下载 pdf 文件,打开 pdf 文件,可以看到以下内容