java使用模板引擎thymeleaf将html导出为PDF文档
目标及技术:
前言:本篇是在已经创建了一个全新的Maven项目的前提下进行。
目标:使用Java模板引擎 thymeleaf,将html动态模板导出为PDF文档
相关依赖:
<!--web起步依赖-->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
<version>2.0.3.RELEASE</version>
</dependency>
<!--thymeleaf配置-->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-thymeleaf</artifactId>
<version>2.0.3.RELEASE</version>
</dependency>
<!-- Flying Saucer -->
<dependency>
<groupId>org.xhtmlrenderer</groupId>
<artifactId>flying-saucer-pdf</artifactId>
<version>9.1.20</version>
</dependency>
<!--itext-->
<dependency>
<groupId>com.lowagie</groupId>
<artifactId>itext</artifactId>
<version>2.1.7</version>
</dependency>
技术实现代码
1.进行thymeleaf 相关yml配置
spring:
thymeleaf:
prefix: classpath:/templates/
suffix: .html
mode: HTML
encoding: utf-8
servlet.content-type: text/html
cache: false
2.生成单个PDF文档实现
方法一:
// 当下代码是直接在Controller层进行实现
// TEMPLATE 为当前html模板的名称,因为在yml中已经配置了路径及前后缀,所以值直接为html文件名。
private final String TEMPLATE = "test2";
//引入模板引擎,并进构造方法行初始化
private final SpringTemplateEngine templateEngine;
public TestController(SpringTemplateEngine templateEngine) {
this.templateEngine = templateEngine;
}
@GetMapping("getPdf")
public void toPdf(HttpServletResponse response) {
// 根据 Thymeleaf 模板生成 HTML 页面
// Context 为目标填充数据 类型为map类型,key即为html中对应的设置key,vlaue即为展示的值
Context context = new Context();
context.setVariable("name", "safd");
String sHtml = templateEngine.process(TEMPLATE, context);
try {
//创建PDf文件
ITextRenderer renderer = new ITextRenderer();
//获取使用的字体数据(由于对中文字体显示可能会不支持,所以需要主动添加字体数据设置。)
ITextFontResolver fontResolver = renderer.getFontResolver();
// C:\Windows\Fonts 系统自带的语言包,可以自选 直接引用;
//但需要将字体文件导入到当前项目中,目前位置为 templates/fonts 本人测试可以支持微软雅黑,和宋体,其他字体如需要请自选并测试。
//当前使用为微软雅黑 BaseFont.IDENTITY_H, BaseFont.NOT_EMBEDDED 这两个参数无需变更,更换字体只需要变更字体文件就行
fontResolver.addFont("templates/fonts/msyh.ttc",BaseFont.IDENTITY_H, BaseFont.NOT_EMBEDDED);
//设置文件名称
String sDate = new SimpleDateFormat("yyyyMMdd").format(new Date());
String sTime = new SimpleDateFormat("HHmmssSSS").format(new Date());
String sFileName = sDate+sTime+".pdf";
OutputStream outputStream = response.getOutputStream();
response.reset();
response.setContentType("application/pdf;charset=UTF-8");
response.setHeader("Content-Disposition", "inline;filename=" + URLEncoder.encode(sFileName, "UTF-8"));
//将html生成文档
renderer.setDocumentFromString(sHtml);
renderer.layout();
//将文档写入到输出流中
renderer.createPDF(outputStream);
//关闭流
outputStream.close();
} catch (Exception e) {
e.printStackTrace();
}
}
方法二:
private final String TEMPLATE = "test2";
//引入模板引擎,并进构造方法行初始化
private final SpringTemplateEngine templateEngine;
public TestController(SpringTemplateEngine templateEngine) {
this.templateEngine = templateEngine;
}
@GetMapping("getPdf")
public void toPdf(HttpServletResponse response) {
// 根据 Thymeleaf 模板生成 HTML 页面
// Context 为目标填充数据 类型为map类型,key即为html中对应的设置key,vlaue即为展示的值
Context context = new Context();
context.setVariable("name", "safd");
String sHtml = templateEngine.process(TEMPLATE, context);
try {
//创建PDf文件
ITextRenderer renderer = new ITextRenderer();
//获取使用的字体数据(由于对中文字体显示可能会不支持,所以需要主动添加字体数据设置。)
ITextFontResolver fontResolver = renderer.getFontResolver();
// C:\Windows\Fonts 系统自带的语言包,可以自选 直接引用;
//但需要将字体文件导入到当前项目中,目前位置为 templates/fonts 本人测试可以支持微软雅黑,和宋体,其他字体如需要请自选并测试。
//当前使用为微软雅黑 BaseFont.IDENTITY_H, BaseFont.NOT_EMBEDDED 这两个参数无需变更,更换字体只需要变更字体文件就行
fontResolver.addFont("templates/fonts/msyh.ttc",BaseFont.IDENTITY_H, BaseFont.NOT_EMBEDDED);
//设置文件名称
String sDate = new SimpleDateFormat("yyyyMMdd").format(new Date());
String sTime = new SimpleDateFormat("HHmmssSSS").format(new Date());
String sFileName = sDate+sTime+".pdf";
OutputStream outputStream = response.getOutputStream();
response.reset();
response.setContentType("application/pdf;charset=UTF-8");
response.setHeader("Content-Disposition", "inline;filename=" + URLEncoder.encode(sFileName, "UTF-8"));
//将html生成document文档
DocumentBuilderFactory documentBuilderFactory = DocumentBuilderFactory.newInstance();
DocumentBuilder builder = documentBuilderFactory.newDocumentBuilder();
Document document = builder.parse(new InputSource(new StringReader(html)));
renderer.setDocument(document, null);
renderer.layout();
renderer.createPDF(outputStream);
//关闭流
outputStream.close();
} catch (Exception e) {
e.printStackTrace();
}
}
3.生成多页PDF文档实现
说明:主要也是针对上面两中方法进行调整即可,就无需附上完整代码了。
思路方法:既提前生成多个html页面的 模板字符串集合,然后遍历集合进行文档添加。需要注意一开始页面实现方式改变,变更示例代码如下:
//生成第一页
renderer.setDocumentFromString(sHtml);
renderer.layout();
//创建时新增false 参数表示当前文档为结束
renderer.createPDF(outputStream,false);
//生成中间页
renderer.setDocumentFromString(sHtml);
renderer.layout();
//生成中间页需要传入当前是第几页
renderer.writeNextDocument(1);
//生成中间页
renderer.setDocumentFromString(sHtml);
renderer.layout();
renderer.writeNextDocument(2);
//所有页面都生成完成;需要进行文档的关闭
renderer.finishPDF();
//关闭流
outputStream.close();
注意点:
1.ITextRenderer 对象只有一个
2.第一页生成时必须传入第二个 false 参数,表示文档未结束
3.中间页必须传入第几页表示
4.所有文档生成完成必须关闭文档
5.最后关闭相关流