java使用html模板导出pdf(使用thymeleaf进行渲染)
·
- 依赖
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-thymeleaf</artifactId>
</dependency>
<dependency>
<!-- ALWAYS required. -->
<groupId>com.openhtmltopdf</groupId>
<artifactId>openhtmltopdf-core</artifactId>
<version>1.0.0</version>
</dependency>
<dependency>
<!-- Required for PDF output. -->
<groupId>com.openhtmltopdf</groupId>
<artifactId>openhtmltopdf-pdfbox</artifactId>
<version>1.0.0</version>
</dependency>
- 工具类
package com.shell.common.utils.pdf;
import com.openhtmltopdf.pdfboxout.PdfRendererBuilder;
import org.springframework.util.ResourceUtils;
import org.thymeleaf.context.Context;
import org.thymeleaf.spring5.SpringTemplateEngine;
import org.thymeleaf.templateresolver.ClassLoaderTemplateResolver;
import java.io.OutputStream;
import java.util.Map;
public class PdfUtil {
/**
* @param os
* @param pdfFileName pdf文件名称(不包含pdf后缀)
* @param templateName 模板名称
* @param variables 模板变量
*/
public static void buildPdf(OutputStream os, String pdfFileName, String templateName, Map<String, Object> variables) throws Exception {
//构造模板引擎
ClassLoaderTemplateResolver resolver = new ClassLoaderTemplateResolver();
resolver.setPrefix("templates/");//模板所在目录,相对于当前classloader的classpath。
resolver.setSuffix(".html");//模板文件后缀
SpringTemplateEngine templateEngine = new SpringTemplateEngine();
templateEngine.setTemplateResolver(resolver);
//构造上下文(Model)
Context context = new Context();
context.setVariable("templateName", templateName);
context.setVariable("pdfFileName", pdfFileName);
context.setVariables(variables);
//渲染模板
String example = templateEngine.process(templateName, context);
PdfRendererBuilder builder = new PdfRendererBuilder();
builder.useFont(ResourceUtils.getFile("classpath:templates/fonts/simsun.ttf"), "simsun");
builder.useFastMode();
builder.withHtmlContent(example, ResourceUtils.getURL("classpath:templates/img/").toString());
builder.toStream(os);
builder.run();
}
}
- 测试代码
package com.step.pdf.demo.controller;
import com.step.pdf.demo.util.PdfUtil;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RestController;
import javax.servlet.http.HttpServletResponse;
import java.util.Arrays;
import java.util.HashMap;
import java.util.Map;
@RestController
public class DemoController {
@GetMapping("pdf")
public void test(HttpServletResponse response) throws Exception {
Map<String, Object> variables = new HashMap<>();
variables.put("assessmentTypeName", "测试");
variables.put("staffName", "staffName");
variables.put("functions", "functions");
variables.put("assessmentDate", "assessmentDate");
variables.put("roles", "roles");
variables.put("score", "score");
variables.put("signature", "signature");
PdfUtil.buildPdf(response, "用于测试的pdf", "parent", variables);
}
}
- 模板代码
<!DOCTYPE html>
<html xmlns:th="http://www.thymeleaf.org" lang="en">
<head>
<meta charset="UTF-8" />
<title th:text="${pdfFileName}"></title>
<style>
@page {
size: A4;
@top-center {
content: element(header);
}
@bottom-center {
font-family: 'simsun', serif;
}
}
html,
body {
font-family: 'simsun', serif;
font-size: 14px;
}
table {
-fs-table-paginate: paginate;
border-collapse: collapse;
width: 100%;
}
.headingBox {
font-size: 18px;
text-align: center;
font-style: italic;
font-weight: bolder;
}
table,
td,
th {
border: 0px solid #555;
padding: 3px 5px;
}
.box1,
.box2,
.box3 {
padding: 10px 20px;
border-top: 1px solid #999;
}
.trBox {
display: flex;
}
.tdBox {
width: 50%;
display: flex;
}
.titleBox {
display: inline-block;
width: 32%;
font-weight: bold;
}
.contentBox {
width: 68%;
color: cornflowerblue;
}
.titleOverviewBox {
display: inline-block;
width: 64%;
font-weight: bold;
}
.contentOverViewBox {
width: 36%;
color: cornflowerblue;
}
.functionTitleBox,
.commentsTitleBox {
font-style: italic;
font-weight: bolder;
margin: 0 0 0 2%;
}
</style>
<style>
#app {
border: 1px solid #999;
width: 550px;
box-sizing: border-box;
margin: 0px auto;
}
#comm {
height: 100px;
}
#content {
white-space: pre-line;
}
</style>
</head>
<body>
<div id="app">
<h3 th:text="'Competence Assessment_'+${assessmentTypeName}" class="headingBox"></h3>
<div class="box1">
<table border="0px;" class="baseInfoBox">
<tr class="trBox">
<td class="tdBox"><span class="titleBox">Name:</span><span class="contentBox" th:text="${staffName}"></span></td>
<td class="tdBox"></td>
</tr>
<tr class="trBox">
<td class="tdBox"><span class="titleBox">Function:</span><span class="contentBox" th:text="${functions}"></span></td>
<td class="tdBox"><span class="titleOverviewBox">Date:</span><span class="contentOverViewBox"
th:text="${assessmentDate}"></span></td>
</tr>
<tr class="trBox">
<td class="tdBox"><span class="titleBox">Role:</span><span class="contentBox" th:text="${roles}"></span></td>
<td class="tdBox"><span class="titleOverviewBox">Agreegate Source:</span>
<span class="contentOverViewBox" th:text="${agreegateSource}"></span></td>
</tr>
</table>
</div>
<div th:each="item:${questionList}">
<div class="box1">
<h4 class="functionTitleBox" th:text="${item.functionName}+':'"></h4>
<div class="w">
<tbody th:border="0">
<tr>
<td th:text="${item.questionContent}" id="content"></td>
</tr>
</tbody>
</div>
</div>
<div class="box1">
<h4 class="commentsTitleBox">Comments:</h4>
<div class="c" th:height="500px" id="comm">
</div>
<div style="display: flex;">
<div style="padding-left: 18em">
<span th:text="'Score: '"></span><span
th:text="'Signature:'"></span></div>
</div>
</div>
</div>
</div>
</body>
</html>
魔乐社区(Modelers.cn) 是一个中立、公益的人工智能社区,提供人工智能工具、模型、数据的托管、展示与应用协同服务,为人工智能开发及爱好者搭建开放的学习交流平台。社区通过理事会方式运作,由全产业链共同建设、共同运营、共同享有,推动国产AI生态繁荣发展。
更多推荐


所有评论(0)