Thymeleaf实现自定义模板导出pdf或word
Posted 萧何~
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Thymeleaf实现自定义模板导出pdf或word相关的知识,希望对你有一定的参考价值。
技术栈:springboot+thymeleaf+pdf引擎
1.导入对应的jar包,使用srpingboot快速实现
<!--引入thymeleaf相关的依赖--> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-thymeleaf</artifactId> </dependency> <!--用于pdf的页面渲染自带webkit浏览器内核--> <dependency> <groupId>com.openhtmltopdf</groupId> <artifactId>openhtmltopdf-core</artifactId> <version>1.0.0</version> </dependency> <dependency> <groupId>com.openhtmltopdf</groupId> <artifactId>openhtmltopdf-pdfbox</artifactId> <version>1.0.0</version> </dependency>
2.生成模板的java代码实现,文件路径需要修改您对应的位置
/** * 本地 *构建一个pdf * @param templateName 模板名称 * @param variables 模板变量 * @throws Exception */ public static void buildResource( String templateName, Map<String, Object> variables) throws Exception { //thymeleaf构造模板引擎;给html文件赋值 ClassLoaderTemplateResolver resolver = new ClassLoaderTemplateResolver(); //默认是找classpath路径下的资源 resolver.setPrefix("testPDF/templates/"); resolver.setSuffix(".html");//模板文件后缀 SpringTemplateEngine templateEngine = new SpringTemplateEngine(); templateEngine.setTemplateResolver(resolver); //构造上下文 Context context = new Context(); context.setVariable("templateName",templateName); //设置变量 context.setVariables(variables); //TODO 渲染模板,返回的生成的模板的字符串 String example = templateEngine.process("parent", context); // 生成pdf文件地址 String pdfPath ="D://"+ new Random().nextInt(30) + "-" + System.nanoTime() + ".pdf"; File file = new File(pdfPath); file.createNewFile(); FileOutputStream os = new FileOutputStream(file); //构建pdf的预览 PdfRendererBuilder builder = new PdfRendererBuilder(); //设置字体支持中文 builder.useFont(new ClassPathResource("testPDF/fonts/simsun.ttf").getFile(), "simsun"); //使用快速渲染器 builder.useFastMode(); //String s = ResourceUtils.getURL("testPDF/templates/").toString(); 获取资源路径 String path = new ClassPathResource("/testPDF/templates").getPath();//获取项目下的资源路径 //withHtmlContent()参数一是模板,参数二模板的基础路径 builder.withHtmlContent(example,new ClassPathResource("/testPDF/templates").getPath()); //输出pdf的结果 builder.toStream(os); builder.run(); //设置字符编码 PrintWriter writer = new PrintWriter(new OutputStreamWriter(os)); writer.flush(); writer.close(); } /** * TODO 通过接口接口请求生成pdf模板;有pdf预览窗口 * @param templateName * @param variables * @throws Exception */ public static void requestBuildResource(HttpServletResponse response, String templateName, Map<String, Object> variables) throws Exception { //thymeleaf构造模板引擎;给html文件赋值 ClassLoaderTemplateResolver resolver = new ClassLoaderTemplateResolver(); //默认是找classpath路径下的资源 resolver.setPrefix("testPDF/templates/"); resolver.setSuffix(".html");//模板文件后缀 SpringTemplateEngine templateEngine = new SpringTemplateEngine(); templateEngine.setTemplateResolver(resolver); //构造上下文(Model) Context context = new Context(); //设置变量 context.setVariables(variables); //TODO 渲染模板,返回的生成的模板的字符串 String example = templateEngine.process(templateName, context); //TODO 生成pdf,浏览器进行展示 response.setHeader("Content-Disposition", "filename=" + new String(("pdfFileName" + ".pdf").getBytes(), "iso8859-1")); //生成pdf,浏览器不进行展示,默认附件下载;原因:attachment标记以附件方式下载保存 // response.setHeader("Content-Disposition", "attachment;fileName=" + new String(("templateName" + ".pdf").getBytes("gb2312"), "ISO8859-1")); OutputStream os = response.getOutputStream(); //构建pdf的构造器 PdfRendererBuilder builder = new PdfRendererBuilder(); //设置字体支持中文 // builder.useFont(new ClassPathResource("testPDF/fonts/simsun.ttf").getFile(), "simsun"); builder.useFastMode(); //withHtmlContent()参数:提供一个包含要转换为PDF的XHTML/XML的字符串 //ResourceUtils.getURL()获取资源的地址 builder.withHtmlContent(example, ResourceUtils.getURL("testPDF/templates/").toString()); //输出pdf的结果 builder.toStream(os); builder.run(); //设置字符编码 PrintWriter writer = new PrintWriter(new OutputStreamWriter(os)); writer.flush(); writer.close(); } /** * 生成本地word * @param variables 模板需要的数据 * @throws Exception */ public static void buildWord( Map<String, Object> variables) throws Exception { ClassLoaderTemplateResolver resolver = new ClassLoaderTemplateResolver(); //默认是找classpath路径下的资源 resolver.setPrefix("testPDF/templates/"); resolver.setSuffix(".html");//模板文件后缀 SpringTemplateEngine templateEngine = new SpringTemplateEngine(); templateEngine.setTemplateResolver(resolver); //构造上下文 Context context = new Context(); context.setVariables(variables); // 生成word文件地址 String pdfPath ="D://"+ new Random().nextInt(30) + "-" + System.nanoTime() + ".docx"; File file = new File(pdfPath); file.createNewFile(); FileOutputStream os = new FileOutputStream(file); try( PrintWriter writer = new PrintWriter(new OutputStreamWriter(os))) { //TODO 参数一是模板;参数二:上下文数据模板需要读取的数据容器;参数三writer输出流是指定输出到那个地方 templateEngine.process("one",context, writer); }catch (Exception e){ log.error("导出word文件出错啦:{}", e.getMessage()); } } /** * 通过接口生成word * @param response * @param variables * @throws Exception */ public static void requestbuildWord(HttpServletResponse response, Map<String, Object> variables) throws Exception { ClassLoaderTemplateResolver resolver = new ClassLoaderTemplateResolver(); //默认是找classpath路径下的资源 resolver.setPrefix("testPDF/templates/"); resolver.setSuffix(".html");//模板文件后缀 SpringTemplateEngine templateEngine = new SpringTemplateEngine(); templateEngine.setTemplateResolver(resolver); //构造上下文 Context context = new Context(); context.setVariable("templateName", "one"); context.setVariables(variables); // 生成word文件地址 response.setCharacterEncoding("utf-8"); response.setContentType("application/msword"); response.setHeader("Content-Disposition", "attachment;fileName=" + new String(("test" + ".xls").getBytes("gb2312"), "ISO8859-1")); try( PrintWriter writer = new PrintWriter(new OutputStreamWriter(response.getOutputStream()))) { //TODO 参数一是模板;参数二:上下文数据模板需要读取的数据容器;参数三writer输出流是指定输出到那个地方 templateEngine.process("parent",context, writer); }catch (Exception e){ log.error("导出word文件出错啦:{}", e.getMessage()); } }
3.thymeleaf模板代码,自定义模板需要了解thymeleaf语法,可自行搜索thymeleaf官网学习
注意导出pdf一定要用这个parent父页面,先引入执行,原因父页面设置的中文编码的使用,防止导出中文乱码
parent页面代码
<!DOCTYPE html> <html xmlns:th="http://www.thymeleaf.org" lang="en"> <head> <meta charset="UTF-8"/> <title >父页面</title> <style> @page { size: A4; @top-center { content: element(header); } @bottom-center { content: \'自由行产品详情\'; font-family: \'simsun\', serif; } } html, body { font-family: \'simsun\', serif; } table { -fs-table-paginate: paginate; border-collapse: collapse; } table, td, th { border: 1px solid #555; padding: 3px 5px; } th { background-color: #eff3fa; } #page-header { position: running(header); border-bottom: 1px solid #555; padding: 5px; } #page-header-text { font-size: 16px; } #page-header-num:after { float: right; text-align: right; content: counter(page) \'/\' counter(pages); } </style> </head> <body> <div id="page-header"> <span id="page-header-text">kindleboy</span> <span id="page-header-num"></span> </div> <div th:include="${templateName}::body"></div> </body> </html>
测试模板页面代码,自行编辑
<!DOCTYPE html> <html lang="en" xmlns:th="http://www.thymeleaf.org"> <head> <meta charset="UTF-8"/> <title>Title</title> </head> <body> <div> <p>测试导出pdf</p> <p th:text="\'weclcome to guangzhou,\'+${user.username}">静态数据</p> </div> </body> </html>
字体中文设置文件:simsun.ttf
下面链接获取设置simsun.tff文件链接
链接:https://pan.baidu.com/s/1FkGDX9VcM4XNAlLuvvDQmA
提取码:tdqa
注意功能发布到linux服务器上,读取字体文件一定要用流的方式读取simsun.tff文件,防止读取不了
以上是关于Thymeleaf实现自定义模板导出pdf或word的主要内容,如果未能解决你的问题,请参考以下文章