1. 对pom文件进行引入
<!--freemarker模板 --> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-freemarker</artifactId> </dependency> <!--pdf生成器 --> <dependency> <groupId>org.xhtmlrenderer</groupId> <artifactId>flying-saucer-pdf</artifactId> <version>9.0.9</version> </dependency> <dependency> <groupId>org.springframework</groupId> <artifactId>spring-test</artifactId> <version>RELEASE</version> </dependency>
2. 转换的流程思路
(1) 读取静态文件模板,将数据进行动态显示
(2)利用freemark模板生成器将ftl模板生成html静态文件
(3)将静态文件转化为流的方式,利用pdf模板将流转化为pdf文件
坑点:pdf模板默认中文不显示,需要引入外界字体,静态文件一般读取到的是target中,文件读取不到,建议采用绝对路径的方式,将路径配置到application.yml中
(4)可以将pdf文件转化为流,上传到文件系统
3. 方法代码(后台代码)
@Override public R<FileVO> getRedSet(Integer id) { log.info("开始进行套红。。。。。。。。。。。"); //获取模板对象 Template template = null; try { //获取自定义的模板对象 template = freemarkerConfig.getTemplate("redset.ftl"); } catch (IOException e) { e.printStackTrace(); } //通过id查找公文信息 OaOfficialDocument oaOfficialDocument = oaOfficialDocumentService.getById(id); //存放页面输出的参数 Map<String, OaOfficialDocument> param = new HashMap(); //用于页面绑定参数 param.put("oaOfficialDocument", oaOfficialDocument); //获取html转化为pdf对象 ITextRenderer renderer = new ITextRenderer(); try { //在配置文件中存放字体信息用于读取配置文件的路径 String filePath = applicationContext.getEnvironment().getProperty("zhxy.fontfile"); //在模板中添加字体信息,默认模板的非字体不显示中文 renderer.getFontResolver().addFont(filePath, BaseFont.IDENTITY_H, BaseFont.NOT_EMBEDDED); } catch (DocumentException e) { e.printStackTrace(); } catch (IOException e) { e.printStackTrace(); } try (StringWriter writer = new StringWriter();) { //将html模板转化为流信息 template.process(param, writer); writer.flush(); //将html流信息写入到pdf中 renderer.setDocumentFromString(writer.toString()); } catch (TemplateException e) { e.printStackTrace(); } catch (IOException e) { e.printStackTrace(); } renderer.layout(); //用来定义一个存储pdf的流信息 byte[] fileBytes = null; try (ByteArrayOutputStream byteArrayOutputStream = new ByteArrayOutputStream();) { //将创建的pdf文件的流信息,写入到定义的流中 renderer.createPDF(byteArrayOutputStream); fileBytes = byteArrayOutputStream.toByteArray(); } catch (DocumentException e) { e.printStackTrace(); } catch (IOException e) { e.printStackTrace(); } MultipartFile file = null; //将byte数组转化为写入流 try (InputStream inputStream = new ByteArrayInputStream(fileBytes);) { //将写入流转化为MockMultipartFile对象 file = new MockMultipartFile("file", "file.pdf", ContentType.APPLICATION_OCTET_STREAM.toString(), inputStream); } catch (IOException e) { e.printStackTrace(); } //调用远程的fegin接口将文件上传到minIo中 R<FileVO> pdfFile = remoteFileUploadService.upload(file); log.info("套红结束。。。。。。。。。。"); return pdfFile; }
4. 前台代码
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd"> <html xmlns="http://www.w3.org/1999/xhtml"> <head> <title>正文套红</title> <meta http-equiv="content-type" content="text/html;charset=utf-8"/> <style type="text/css"> *{ margin: 0; padding: 0; } .box{ width: 100%; background: #fff; margin: 0 auto; } .box .line{ width: 100%; height: 5px; background-color: #e60012; margin-top: 40px; } .box .title{ width: 100%; position: relative; padding-left: 50px; box-sizing: border-box; } .box .title .names{ font-size: 45px; float: left; } .box .title .names div{ color: #e60012; } .box .title .names div:first-child{ margin-bottom: 32px; } .box .title .names span{ display: inline-block; width: 30px; } .box .title .word{ font-size: 45px; writing-mode:horizontal-tb; line-height: 108px; color: #e60012; float: right; padding-right: 80px; } .parent{ width: 100%; height: 120px; } .main{ padding: 15px 10px; } </style> </head>
<!--指定引入的字体类型 -->
<body style="font-family: SimHei;">
<div class="box">
<div class="title">
<div class="parent">
<div class="names">
<div>三门峡社会管理职业学院</div>
<div>三<span></span>门<span></span>峡<span></span>技<span></span>师<span></span>学<span></span>院</div>
</div>
<div class="word">文件</div>
</div>
</div>
<div class="line"></div>
<div class="main">
${oaOfficialDocument.docText}
</div>
</div>
</body>
</html>