700字范文,内容丰富有趣,生活中的好帮手!
700字范文 > 利于iText实现html或者freemark等模板生成PDF

利于iText实现html或者freemark等模板生成PDF

时间:2019-01-03 14:01:33

相关推荐

利于iText实现html或者freemark等模板生成PDF

pdf:/chenpi/p/5534595.html

word:/mini-firework/p/4934337.html

/zhongshiqiang/p/5764857.html

/question/1950390666261025228.html

文章目录

html 或 freemarker 生成 pdf测试用例注意事项中文字体simsun.ttc下载

html 或 freemarker 生成 pdf

1、导入所需要的maven依赖

<!-- html 转 pdf 所需要的依赖于--><dependency><groupId>org.xhtmlrenderer</groupId><artifactId>core-renderer</artifactId><version>R8</version></dependency><!-- freemarker 所需依赖于--><dependency><groupId>org.freemarker</groupId><artifactId>freemarker</artifactId><version>2.3.28</version></dependency><!-- html 转 xhtml 所需依赖--><dependency><groupId>net.sf.jtidy</groupId><artifactId>jtidy</artifactId><version>r938</version></dependency><!-- StringUtils 字符串工具类所需依赖 --><dependency><groupId>mons</groupId><artifactId>commons-lang3</artifactId></dependency>

2、准备好一份html或freemarker模板文件,在html或freemarker转pdf时,会出现中文乱码或者中文不显示的问题,故我们需要在html或freemarker中引入外部的中文字体库,这里使用的是simsun.ttc,需要在html或freemark加入相应代码,如下所示:simsun.ttc下载地址

在html或freemark中加入:

<style type="text/css">/*解决html转pdf文件中文不显示的问题*/body {font-family: SimSun;}/*设定纸张大小*//* A4纸 *//* @page{size:210mm*297mm} */@page{size:a4}</style>

3、PdfUtil工具类

package com.example.demo.pdf;import com.lowagie.text.DocumentException;import com.lowagie.text.pdf.BaseFont;import freemarker.cache.FileTemplateLoader;import freemarker.cache.TemplateLoader;import freemarker.template.Configuration;import freemarker.template.Template;import freemarker.template.TemplateException;import mons.lang3.StringUtils;import org.w3c.tidy.Tidy;import org.xhtmlrenderer.pdf.ITextFontResolver;import org.xhtmlrenderer.pdf.ITextRenderer;import java.io.*;import java.util.*;/*** @description:* @author: chenmingjian* @date: 19-4-24 10:25*/public class PdfUtil {/*** html 转 pdf* @param htmlFilePath html文件存储的绝对路径,如:/home/chenmingjian/pdf/result.html* @param pdfFilePath 生成的pdf文件存储绝对路径,如:/home/chenmingjian/pdf/测试.pdf* @param fontPath 字体存储绝对路径,如:/home/chenmingjian/pdf/simsun.ttc*/public static void htmlToPdf(String htmlFilePath, String pdfFilePath, String fontPath) throws DocumentException, IOException {OutputStream os = null;try {os = new FileOutputStream(pdfFilePath);ITextRenderer renderer = new ITextRenderer();renderer.setDocument(htmlFilePath);// 解决中文不显示问题ITextFontResolver fontResolver = renderer.getFontResolver();fontResolver.addFont(fontPath, BaseFont.IDENTITY_H, BaseFont.NOT_EMBEDDED);renderer.layout();renderer.createPDF(os);} finally {if(os != null) {os.close();}}}/*** freemarker 转 pdf* @param freemarkerTemplateFilePath freemarker模板的绝对路径,如:/home/chenmingjian/pdf/template.ftl* @param pdfFilePath 导出pdf的绝对路径,如:/home/chenmingjian/pdf/测试.pdf* @param data 动态装载freemarker的数据* @param fontPath 字体的绝对路径,,如:/home/chenmingjian/pdf/simsun.ttc*/public static void freemarkerToPdf(String freemarkerTemplateFilePath, String pdfFilePath, Map<String, Object> data, String fontPath) throws IOException, TemplateException, DocumentException {String filePath = StringUtils.substringBeforeLast(freemarkerTemplateFilePath, "/") + "/";String resultHtmlPath = filePath + System.currentTimeMillis() + "result.html";freemarkerToHtml(freemarkerTemplateFilePath,data,resultHtmlPath);htmlToPdf(resultHtmlPath,pdfFilePath,fontPath);deleteFileByPath(resultHtmlPath);}/*** freemarker 转 html* @param freemarkeremplateFilePath 模板文件的绝对路径,如:/home/chenmingjian/pdf/template.ftl* @param data 填充模板的数据* @param resultHtmlPath 生成指定文件的绝对路径,如:/home/chenmingjian/pdf/result.html*/private static void freemarkerToHtml(String freemarkerTemplateFilePath, Map<String, Object> data,String resultHtmlPath) throws IOException, TemplateException {Writer out = null;try {out = new BufferedWriter(new OutputStreamWriter(new FileOutputStream(resultHtmlPath), "UTF-8"));Template temp = getTemplate(freemarkerTemplateFilePath);temp.setEncoding("UTF-8");temp.process(data, out);} finally {if (out != null) {out.close();}}}/*** 通过路径和文件名称找模板* @param templateFilePath 模板文件的绝对路径,如:/home/chenmingjian/pdf/template.ftl* @return*/private static Template getTemplate(String templateFilePath) throws IOException {Configuration cfg = new Configuration();cfg.setClassicCompatible(true);String filePath = StringUtils.substringBeforeLast(templateFilePath, "/") + "/";String fileName = StringUtils.substringAfterLast(templateFilePath, "/");TemplateLoader templateLoader = new FileTemplateLoader(new File(filePath));cfg.setTemplateLoader(templateLoader);return cfg.getTemplate(fileName);}/*** 删除文件* @param filePath*/private static void deleteFileByPath(String filePath){File file = new File(filePath);if(file.exists() && file.isFile()) {file.delete();}}/*** 转化类** @param html html文件输入路径(带文件名称)* @param xhtml xhtml文件输入路径(带文件名称)* @return*/public static void htmlToXhtml(String html, String xhtml) throws IOException {FileInputStream fin = null;ByteArrayOutputStream byteArrayOut = null;ByteArrayInputStream tidyInput = null;ByteArrayOutputStream tidyOut = null;try {fin = new FileInputStream(html);byteArrayOut = new ByteArrayOutputStream();int data;while ((data = fin.read()) != -1) {byteArrayOut.write(data);}byte[] htmlFileData = byteArrayOut.toByteArray();tidyInput = new ByteArrayInputStream(htmlFileData);tidyOut = new ByteArrayOutputStream();Tidy tidy = new Tidy();tidy.setInputEncoding("UTF-8");tidy.setOutputEncoding("UTF-8");tidy.setShowWarnings(false);tidy.setIndentContent(true);tidy.setSmartIndent(true);tidy.setIndentAttributes(false);tidy.setMakeClean(true);tidy.setQuiet(true);tidy.setWord2000(true);tidy.setXHTML(true);tidy.setErrout(new PrintWriter(System.out));tidy.parse(tidyInput, tidyOut);tidyOut.writeTo(new FileOutputStream(xhtml));tidyOut.flush();} finally {if(fin != null){fin.close();}if(byteArrayOut != null){byteArrayOut.close();}if(tidyInput != null){tidyInput.close();}if(tidyOut != null){tidyOut.close();}}}}

测试用例

测试类代码:

package com.example.demo.pdf;import com.lowagie.text.DocumentException;import freemarker.template.TemplateException;import lombok.Data;import lombok.extern.slf4j.Slf4j;import org.junit.runner.RunWith;import org.springframework.boot.test.context.SpringBootTest;import org.springframework.test.context.junit4.SpringRunner;import java.io.IOException;import java.io.Serializable;import java.util.*;/*** @description:* @author: chenmingjian* @date: 19-4-24 15:02*/@Slf4j@RunWith(SpringRunner.class)@SpringBootTestpublic class Test {/*** html 转 pdf*/@org.junit.Testpublic void htmlToPdf(){String htmlPath = "/home/chenmingjian/pdf/html.html";String pdfPath = "/home/chenmingjian/Downloads/测试.pdf";String chineseFontPath = "/home/chenmingjian/pdf/" + "simsun.ttc";try {PdfUtil.htmlToPdf(htmlPath,pdfPath,chineseFontPath);} catch (IOException | DocumentException e) {log.error("html 转 pdf 失败, 失败原因:{}",e);}}/*** freemarker 转 pdf*/@org.junit.Testpublic void freemarkerToPdf(){String freemarkerPath = "/home/chenmingjian/pdf/template.ftl";String pdfPath = "/home/chenmingjian/Downloads/测试.pdf";String chineseFontPath = "/home/chenmingjian/pdf/" + "simsun.ttc";Map<String, Object> data = initData();try {PdfUtil.freemarkerToPdf(freemarkerPath,pdfPath,data,chineseFontPath);} catch (IOException | DocumentException | TemplateException e) {log.error("freemarker 转 pdf 失败, 失败原因:{}",e);}}public static HashMap<String, Object> initData() {HashMap<String, Object> needReplaceMapData = new HashMap<String, Object>();/******************************************单个属性************************************/needReplaceMapData.put("name", "刘亦菲");/******************************************list 属性添加***********************************/List<Student> students = new ArrayList<Student>();for (int i = 0; i < 2; i++) {Student student = new Student();student.setId(i);student.setName(" 葫芦娃" + i + "号");students.add(student);}needReplaceMapData.put("students", students);/******************************************日期 ***********************************/needReplaceMapData.put("date", new Date());needReplaceMapData.put("showDate", true);needReplaceMapData.put("imgUrl", "/translate/344/w700h1244/0410/B_F_-fyzeyqa1740187.jpg");needReplaceMapData.put("description", "描述一只猫");return needReplaceMapData;}@Datapublic static class Student implements Serializable {private Integer id;private String name;}}

测试类中html所需的模板html.html:

<!DOCTYPE html><html lang="en"><head><meta http-equiv="Content-Type" content="text/html; charset=utf-8"/><title>认识table表标签</title><style type="text/css">/*解决html转pdf文件中文不显示的问题*/body {font-family: SimSun;}/*设定纸张大小*//* A4纸 *//* @page{size:210mm*297mm} */@page{size:a4}p {color: red;}</style></head><body><table border="1px"><caption>我的标题</caption><tbody><tr><th>班级</th><th>学生数</th><th>平均成绩</th><th>班级</th><th>学生数</th><th>平均成绩</th><th>班级</th><th>学生数</th><th>平均成绩</th></tr><tr><td>一班</td><td>30</td><td>89</td><td>一班</td><td>30</td><td>89</td><td>一班</td><td>30</td><td>89</td></tr><tr><td>一班</td><td>30</td><td>89</td><td>一班</td><td>30</td><td>89</td><td>一班</td><td>30</td><td>89</td></tr><tr><td>一班</td><td>30</td><td>89</td><td>一班</td><td>30</td><td>89</td><td>一班</td><td>30</td><td>89</td></tr></tbody></table><p>《侠客行》<br/>年代: 唐 作者: 李白<br/>赵客缦胡缨,吴钩霜雪明。银鞍照白马,飒沓如流星。十步杀一人,千里不留行。事了拂衣去,深藏身与名。闲过信陵饮,脱剑膝前横。将炙啖朱亥,持觞劝侯嬴。三杯吐然诺,五岳倒为轻。眼花耳热后,意气素霓生。救赵挥金槌,邯郸先震惊。千秋二壮士,煊赫大梁城。纵死侠骨香,不惭世上英。谁能书閤下,白首太玄经。</p></body></html>

测试类中freemarker所需的模板freemarker.ftl:

<html><head><title>Welcome FreeMarker!</title><meta charset="utf-8"></meta><meta name="viewport" content="width=device-width, initial-scale=1"></meta><meta http-equiv="x-ua-compatible" content="ie=edge"></meta><link rel="icon" href="/hcode/images/favicon.ico"></link><script src="/jquery/jquery-1.8.3.min.js"></script><script src="/highcharts/highcharts.js"></script><style type="text/css">/*解决html转pdf文件中文不显示的问题*/body {font-family: SimSun;}/*设定纸张大小*//* A4纸 *//* @page{size:210mm*297mm} */@page{size:a4}</style></head><body><#-- 单个属性 替换 --><h1>Welcome ${name}</h1><img src="${imgUrl}"class="shrinkToFit" height="474" width="266"/><#-- list 属性替换 --><table border="1"><#list students as student><tr><td>${student.name} </td><td>${student.id}</td></tr></#list></table><#--常用指令--><#--1. 赋值 =左边是要赋值的变量 , = 右边是从map 中传递值,在freemarker 标签中可以直接调用变量名获取后台传递的值,不需要+${} --><#assign showDate = showDate/><#--2. 判断 --><#if showDate == true> 现在时间是:${date?string('yyyy-MM-dd')}<#else>就不给你显示,来一百块</#if><#-- 3. 处理未定义变量或值为null ,当定义的变量为空或者未定义,默认情况下 --><#-- 3.1 设置默认值 防止未输入字段,空指针异常--><h1> 葫芦玩总共有几个 ?答: ${number !8} </h1><h1> 小明的车是神马牌子 ? 答:${(student.car.sign) !'宝马741'} </h1><#-- 3.2 加if 判断--><#if weather??> Hi,${weather}<#else> 今天天气信息没有获取到,你就看做是晴天吧,反正也没下雨</#if><#if (user.car.sign)? exists>Hi,${user} </#if><#-- 3.3 修改全局配置 --><#setting classic_compatible=true><h1> 小洋人的价钱是: ${price} 元 </h1><#-- 4. 格式化输出--><#-- 转成字符串显示 -->${12.6?c} <br/><#-- 按数字显示 -->${123456 ?string.number} <br/><#-- 按贷币格式显示 -->${123456 ?string.currency} <br/><#-- 按百分比格式显示 -->${1.12 ?string.percent} <br/><#--去空格 -->${description ?trim} <br/><#-- 格式化日期-->${date?string("yyyy-MM-dd HH:mm:ss")} <br/>${date?string("yyyyMMdd")} <br/><#-- 5. 插入其他模块 --><#--<#include "/mime.ftl">--></body></html>

注意事项

1、html 转 pdf 所需依赖的包 xhtmlrender 的局限性

标签:xhtmlrender需要html的标签必须是规范的,即,所有标签必须闭合。

样式:不支持外部样式,所有样式必须写在html内部。

Chart图表:只能识别html中的样式,即不能识别外部样式及脚本。不支持JS脚本,因为后台读取的只是html和css,脚本的执

行需要浏览器执行。即,如果用有图表的话,只能后台生成图表,然后转成图片。

换行:对换行的不良好支持。最佳解决方案是:重写掉xhtmlRenderer里面的Break类。

分页:如果html里面有图片,而在分页的地方刚好有图片,这个图片将被渲染到下一页,并可能遮挡下页的元素,所以,只能在html中提前控制 分页,即:在div中加入css(style=“page-break-after: always;”)

2、由于xhtmlrender对html要求比较严格,所有html文件可能不能满足生成pdf的条件,所有可以先将html转换成xhtml文件,再调用工具类中的htmlToPdf方法,html转换成xhtml的方法在PdfUtil工具类中有提供,为htmlToXhtml方法

中文字体simsun.ttc下载

中文字体simsun.ttc下载

本内容不代表本网观点和政治立场,如有侵犯你的权益请联系我们处理。
网友评论
网友评论仅供其表达个人看法,并不表明网站立场。