2. html2pdf 使用html或者ftl生产pdf

引入 pom.xml

        <dependency><groupId>com.itextpdf</groupId><artifactId>io</artifactId><version>7.1.5</version></dependency><!--  https://mvnrepository.com/artifact/com.itextpdf/kernel  --><dependency><groupId>com.itextpdf</groupId><artifactId>kernel</artifactId><version>7.1.5</version></dependency><!-- https://mvnrepository.com/artifact/com.itextpdf/layout --><dependency><groupId>com.itextpdf</groupId><artifactId>layout</artifactId><version>7.1.5</version></dependency><!-- https://mvnrepository.com/artifact/com.itextpdf/styled-xml-parser --><dependency><groupId>com.itextpdf</groupId><artifactId>styled-xml-parser</artifactId><version>7.1.5</version></dependency><!--  https://mvnrepository.com/artifact/com.itextpdf/html2pdf  --><dependency><groupId>com.itextpdf</groupId><artifactId>html2pdf</artifactId><version>2.1.2</version></dependency><!-- https://mvnrepository.com/artifact/org.freemarker/freemarker  --><dependency><groupId>org.freemarker</groupId><artifactId>freemarker</artifactId><version>2.3.28</version></dependency><dependency><groupId>org.xhtmlrenderer</groupId><artifactId>flying-saucer-pdf</artifactId><version>9.0.8</version></dependency>

主要工具类ITextUtis

package com.ssish.eoms.util;import com.itextpdf.html2pdf.ConverterProperties;
import com.itextpdf.html2pdf.HtmlConverter;
import com.itextpdf.io.IOException;
import com.itextpdf.kernel.geom.PageSize;
import com.itextpdf.kernel.pdf.PdfDocument;
import com.itextpdf.kernel.pdf.PdfString;
import com.itextpdf.kernel.pdf.PdfWriter;
import com.itextpdf.kernel.pdf.WriterProperties;
import com.itextpdf.layout.font.FontProvider;import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.net.URISyntaxException;/*** @author wyw* @Description iText工具类* @date 2019/7/15 15:36*/
public class ITextUtis {/**字体构建器*/private static ConverterProperties fontProps;/*** 初始化字体解析器* @param resourcePrefix* @return*/private static void initConverterProperties(String resourcePrefix) {fontProps = new ConverterProperties();FontProvider fp = new FontProvider();//fp.addStandardPdfFonts();//标准化PDF字体fp.addDirectory(resourcePrefix);//fp.addSystemFonts();//添加系统字体fontProps.setFontProvider(fp);fontProps.setBaseUri(resourcePrefix);fontProps.setCharset("UTF-8");}/*** html转pdf文件的方法* @param html html内容* @param outFilePath 文件输出位置,如/data/test.pdf* @return 生成的pdf文件路径* @throws Exception*/public static String html2pdf(String html, String outFilePath) throws Exception {PdfDocument pdfDoc = null;FileOutputStream out = null;PdfWriter pdfWriter = null;try {out = new FileOutputStream(outFilePath);WriterProperties writerProperties = new WriterProperties();writerProperties.addXmpMetadata();pdfWriter = new PdfWriter(out, writerProperties);//创建一个空白PDF文档pdfDoc = new PdfDocument(pdfWriter);pdfDoc.setDefaultPageSize(PageSize.A4);//默认A4大小pdfDoc.getCatalog().setLang(new PdfString("zh-CN"));if (null == fontProps) {String fontPath = getResourcesFilePath("template/font/");System.out.println("FontPath===================" + fontPath);initConverterProperties(fontPath);}//开始转换HtmlConverter.convertToPdf(html, pdfDoc, fontProps);pdfWriter.flush();out.flush();return outFilePath;} catch (Exception e) {throw e;} finally {if (null != pdfWriter) {pdfWriter.close();}if (null != out) {out.close();}if (null != pdfDoc && !pdfDoc.isClosed()) {pdfDoc.close();}}}/*** 通过文件名称获取resources资源文件夹下文件绝对路径* @param fileName* @return 模块文件完整路径* @throws URISyntaxException*/public static String getResourcesFilePath(String fileName) throws URISyntaxException {StringBuilder builder = new StringBuilder();//判断是否Linux系统if (System.getProperty("os.name").toLowerCase().indexOf("linux") != -1) {//linux系统在路径前面加/builder.append("/");}//获取项目路径this.getClass()String srcPath = ITextUtis.class.getResource("/").toURI().getPath();System.out.println(srcPath);if (srcPath.contains("WEB-INF")) {builder.append(srcPath.substring(1, srcPath.lastIndexOf("WEB-INF")));} else {builder.append(srcPath.substring(1));}//builder.append("resources/");builder.append(fileName);return builder.toString();}/*** 读取文本文件内容* @author liulei* @version 1.0* @param filePath* @return* @throws Exception*/public static String readToString(String filePath) throws Exception {File file = new File(filePath);Long filelength = file.length();byte[] filecontent = new byte[filelength.intValue()];FileInputStream in = null;try {in = new FileInputStream(file);in.read(filecontent);return new String(filecontent, "UTF-8");} catch (Exception e) {throw e;} finally {if (null != in) {try {in.close();} catch (IOException ex) {ex.printStackTrace();}}}}//测试方法public static void main(String[] args) {try {//String content = readToString("D:/WorkSpace/Test/WebContent/test.html");String content = readToString("D:/workspace_nanyan/eoms/src/main/webapp/template/protocoltest.html");initConverterProperties("D:/workspace_nanyan/eoms/src/main/webapp/template/font/");//指定中文字体位置System.out.println(content);html2pdf(content, "D:/test3.pdf");} catch (Exception e) {e.printStackTrace();}}
}

辅助工具类FreeMarkerConfigurer

package com.ssish.eoms.util;import freemarker.template.Configuration;
import freemarker.template.Template;
import freemarker.template.TemplateException;import java.io.File;
import java.io.IOException;
import java.io.StringWriter;
import java.net.URISyntaxException;
import java.util.Locale;/*** @author wyw* @Description FreeMarker构造器* @date 2019/7/15 10:16*/
public class FreeMarkerConfigurer extends Configuration {/**模板目录位置*/private String templateDirectory;/**默认编码*/private String templateDefaultEncoding = "UTF-8";/**模板刷新时间(单位/毫秒)*/private long templateUpdateDelay;/*** 默认构造函数*/public FreeMarkerConfigurer() {super(Configuration.getVersion());this.setLocale(Locale.CHINESE);this.setDefaultEncoding(templateDefaultEncoding);}/*** 构造函数* @param templateDirectory* @throws IOException*/public FreeMarkerConfigurer(String templateDirectory) {super(Configuration.getVersion());this.setLocale(Locale.CHINESE);this.templateDirectory = templateDirectory;this.setTemplateDirectory(templateDirectory);this.setDefaultEncoding(templateDefaultEncoding);}/*** getTemplateDirectory* @return*/public String getTemplateDirectory() {return templateDirectory;}/*** 设置模板文件目录* @param templateDirectory* @throws IOException*/public void setTemplateDirectory(String templateDirectory) {try {StringBuilder builder = new StringBuilder();//判断是否Linux系统if (System.getProperty("os.name").toLowerCase().indexOf("linux") != -1) {//linux系统在路径前面加/builder.append("/");}//获取项目路径this.getClass()String srcPath = FreeMarkerConfigurer.class.getResource("/").toURI().getPath();//System.out.println("==================srcPath:" + srcPath);if (srcPath.contains("WEB-INF")) {builder.append(srcPath.substring(1, srcPath.lastIndexOf("WEB-INF")));} else {builder.append(srcPath.substring(1));}builder.append(templateDirectory);templateDirectory = builder.toString();this.templateDirectory = templateDirectory;System.out.println("==================TemplateFileDefault:" + templateDirectory);File templateDir = new File(templateDirectory);if (null == templateDirectory || !templateDir.exists()) {throw new RuntimeException("未指定模板文件目录或目录不存在!");}this.setDirectoryForTemplateLoading(templateDir);} catch (IOException e) {throw new RuntimeException(e);} catch (URISyntaxException e) {throw new RuntimeException(e);}}/*** getDefaultEncoding*/public String getTemplateDefaultEncoding() {return templateDefaultEncoding;}/*** 设置默认编码*/public void setTemplateDefaultEncoding(String templateDefaultEncoding) {this.templateDefaultEncoding = templateDefaultEncoding;this.setDefaultEncoding(templateDefaultEncoding);}/*** getTemplateUpdateDelay* @return*/public long getTemplateUpdateDelay() {return templateUpdateDelay;}/*** 设置模板缓存刷新时间(单位/毫秒)* @param templateUpdateDelay*/public void setTemplateUpdateDelay(long templateUpdateDelay) {this.templateUpdateDelay = templateUpdateDelay;this.setTemplateUpdateDelayMilliseconds(templateUpdateDelay);}/*** 获取解析过的模板字符串方法* @Name: getConversionTemplate* @Author: liulei* @Create Date: 2019年4月29日 下午6:14:37* @param fileName* @param dataModel* @return 解析过的模板字符串* @throws TemplateException* @throws IOException*/public String getConversionTemplate(String fileName, Object dataModel)throws TemplateException, IOException {Template template = this.getTemplate(fileName);//加载模板StringWriter writer = new StringWriter();//处理数据template.process(dataModel, writer);writer.close();return writer.toString();}
}

applicationContext.xml 中示例化类FreeMarkerConfigurer

<!-- freeMarker -->
<bean id="freeMarkerConfigurer" class="com.ssish.eoms.util.FreeMarkerConfigurer"lazy-init="true"><property name="templateDirectory" value="template" />  <!-- 这里的template是模板文件和字体文件等放置的目录文件 --><!-- 模板缓存时间(单位/毫秒)<property name="templateUpdateDelay" value="1800000" /> --><!--  --><property name="templateUpdateDelay" value="0" /><!--支持Null值--><property name="classicCompatible" value="true"/>
</bean>

在项目中创建目录 template/font 字体文件DENGB.TTF、fangsong_GB2312.ttf,图片 logo.png放置在 font 目录下,模板文件 protocolTemplate.ftl 放置在template目录下

protocolTemplate.ftl 模板文件内容如下

<html>
<head><meta charset="UTF-8"></meta><title>服务协议</title><meta name="viewport" content="width=device-width,initial-scale=1,minimum-scale=1,maximum-scale=1,user-scalable=no"></meta><style type="text/css">
@page {size:A4;
}
html,
body {background-color: #fff;}* {padding: 0;margin: 0;
}
img {display: block;
}
.relativeAgreement {padding: 10px 15px 30px;
}
.relativeAgreement p {color: #333;
}
.perLineTit1 {margin-bottom: 20px;
}
.perLineTit {font-size: 15px;font-weight: bold;color: #444;text-align: center;
}
.normal {font-size: 15px;color: #444;
}
.indent2em {font-size: 15px;text-indent: 2em;
}
.logoImg {width: 200px;margin: 10px auto 12px;
}
.marginTop30 {margin-top: 20px;
}
.textAlignRight {text-align: right;font-size: 15px;
}
p.normalTit {margin-bottom: 15px;
}
.marginbot {margin-bottom: 140px;
}
</style>
</head>
<body >
<div class="main"><div class="relativeAgreement"><img src="logo.png" alt="" class="logoImg" /><p class="perLineTit">《保险经纪服务委托协议书》</p><p class="perLineTit perLineTit1">授权委托书</p><p class="normal normalTit">致:有关保险公司</p><p class="indent2em">从${(data.year)!}年${(data.month)!}月${(data.day)!}日起,我司委托宇泰保险经纪(北京)有限公司为我司唯一的保险经纪人,代表我们处理所有保险相关事宜。</p><p class="indent2em">除非另行下达了取消该委托书的书面通知,本委托书将持续有效。同时,所有以前有关这方面的委托全部作废。</p><p class="indent2em">宇泰保险经纪(北京)有限公司被授权审核我司的保险计划及安排,并按照其营业执照所规定的营业范围提供风险管理及保险服务。</p><p class="normal">主要服务范围如下:</p><p class="normal">①协助我司安排相关保险;</p><p class="normal">②帮助我司识别未投保风险;</p><p class="normal">③代我司签署保险协议;</p><p class="normal">④帮助我司检查并核对各种保险文件及其他有关风险转移安排的文件,包括保险单和批单;</p><p class="normal">⑤准备保险安排概要;</p><p class="normal">就风险/保险及赔偿等问题向我司提供建议、帮助及指导;</p><p class="normal">⑥与我司举行保险工作会议;</p><p class="normal">⑦检测保险公司的财务稳定性;</p><p class="normal">⑧协助我司进行索赔,帮助并指导我司准备索赔文件。</p><p class="normal marginTop30">委托人:(盖章)<img alt="盖章"  style="vertical-align:middle;margin-left:50px;" src="${(data.imageUrl)!}" /></p><p class="textAlignRight" >${(data.year)!}年${(data.month)!}月${(data.day)!}日</p></div><!-- 标记分页<div style="page-break-after:always; border:1px solid blue;"></div> -->
</div>
</body>
</html>

调用方法主要代码如下

@RequestMapping(value = Urls.SSI_BACK_PROTOCOL_MAKE_SEAL, method = RequestMethod.POST)public void makeSeal(HttpServletResponse response,  String  imgData,String procotolId) throws IOException {JSONObject jb = new JSONObject();SimpleDateFormat sdf = new SimpleDateFormat("yyyyMMddHHmmss");String filePathAdd ="protocol/img/"+sdf.format(new Date())+".png";System.out.println("filePathAdd="+filePathAdd);ossService.upload(new ByteArrayInputStream(Base64.decode(imgData)), filePathAdd);try {String pdfurl = createPDF(response,procotolId,filePathAdd);System.out.println("pdfurl="+pdfurl);jb.put("retFlag", "true");jb.put("pdfurl", pdfurl);} catch (TemplateException e) {jb.put("retFlag", "flase");jb.put("retMsg", e.getMessage());}writeDateToWeb(response, jb);}
public String createPDF(HttpServletResponse response,  String  procotolId,String filePath) throws IOException, TemplateException {log.info("==========================进入生成服务协议pdf");if(StringUtils.isNotBlank(procotolId)){WxServiceAgreement wxServiceAgreement =  protocolService.queryProtocolById(procotolId);if(wxServiceAgreement!=null){//拼接签名储存路径StringBuilder builder = new StringBuilder();ProtocolVo protocolVo = new ProtocolVo();protocolVo.setName(wxServiceAgreement.getClientName());SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd");String cerateStr = sdf.format(wxServiceAgreement.getCreateDate());protocolVo.setYear(cerateStr.substring(0,4));protocolVo.setMonth(cerateStr.substring(5,7));protocolVo.setDay(cerateStr.substring(8,10));String imageUrl = newbeeFileWeb+"/"+newbeeObjectName+filePath;System.out.println("imageUrl="+imageUrl);protocolVo.setImageUrl(imageUrl);try {//PUT数据Map<String, Object> dataMap = new HashMap<String, Object>();dataMap.put("data", protocolVo);String templateName = "protocolTemplate.ftl";//处理模板数据String content = freeMarkerConfigurer.getConversionTemplate(templateName,dataMap);String exportFilePath = "/data/eoms/temp/";//判断文件储存目录是否存在File saveDir = new File(exportFilePath);if (!saveDir.exists()) {saveDir.mkdirs();log.info("============create directory:" + exportFilePath);}exportFilePath = exportFilePath+ wxServiceAgreement.getServiceNo()+".pdf";//将Html文本转换为Pdf文件ITextUtis.html2pdf(content,exportFilePath);log.info("===============exportPdfPath>>>" + exportFilePath);//上传到ossFile pdfFile = new File(exportFilePath);InputStream isZipFile = new FileInputStream(pdfFile);String path="protocol/pdf/"+pdfFile.getName();boolean flag = ossService.upload(isZipFile,path);log.info("===============flag="+flag);log.info("===============path="+path);WxServiceAgreement serviceAgreement = new WxServiceAgreement();serviceAgreement.setId(wxServiceAgreement.getId());serviceAgreement.setFileUrl(newbeeFileWeb+"/"+newbeeObjectName+path);protocolService.updatebyKey(serviceAgreement);pdfFile.delete();return newbeeFileWeb+"/"+newbeeObjectName+path;} catch (Exception e) {e.printStackTrace();}}}return null;}

注意事项:

字体文件和图片放在同一个目录下,模板文件中取图片时,只需写图片名称即可 ,代码如下

<img src="logo.png" alt="" class="logoImg" />

生成后的pdf如下

使用HTML或者FTL(Freemarker模板)生成PDF 示例2相关推荐

  1. Flying-Saucer使用HTML或者FTL(Freemarker模板)生成PDF

    PDF导出工具有itext,但是itext对中文支持不好,还有样式CSS支持也不好,使用IReport比较复杂,上手不太容易,怎么办? 幸好有Flying-Saucer这个项目,帮助我们解决了以上问题 ...

  2. freemarker 模板生成pdf文件并下载

    利用freemarker 模板生成pdf文件,通过浏览器直接下载或生成文件到指定目录 1.pom.xml文件 <!--引入Freemarker的依赖--> <dependency&g ...

  3. freemarker模板生成pdf文件

    文章目录 1.pom依赖 2.ftl模板以及宋体文件 2.1.文件路径 2.2.ftl文件模板(test.ftl) 3.controller生成pdf文件 1.pom依赖 <!--freemar ...

  4. FreeMarker 模板生成 PDF电子凭证/图片

    一.场景 在某些业务场景中,需要提供相关的电子凭证,比如网银/支付宝中转账的电子回单,签约的电子合同等.方便用户查看,下载,打印.目前常用的解决方案是,把相关数据信息,生成对应的pdf文件返回给用户. ...

  5. iText通过FreeMarker模板生成PDF解决方案

    首先定义一个HTML模板,通过后台数据填充,生成PDF文件. 目录 一.所需依赖 二.生成工具类 三.准备模板 四. 字体和模板放置的位置 五.生成PDF文件预览 一.所需依赖 <!-- pdf ...

  6. freemarker根据静态模板和动态模板生成PDF与Word

    背景介绍:最近在做老旧项目的二次开发,所以用到了freemarker去生成PDF和Word,涉及到打印静态模板与动态模板.查看了这方面的资料发现大都不全,似是而非.废话不多说,上案例. freemar ...

  7. freemarker+itext生成PDF文件

    介绍 FreeMarker是一款模板引擎: 即一种基于模板和要改变的数据, 并用来生成输出文本(HTML网页.电子邮件.配置文件.源代码等)的通用工具. 它不是面向最终用户的,而是一个Java类库,是 ...

  8. 根据word模板生成pdf文件

    1.首先建一个word,插入一个表格,需要填充的值用${parame}代替 (注意:这里的参数要和java实体类里面的参数对应起来,代码放在下面) 2.制作完成后另存为xml格式 3.然后用文本编辑工 ...

  9. 利用 freemarker 模板生成 word 小结

    在企业级开发时,不可避免的会遇到生成 word 文档的需求,有两种常用的方案,1.使用 Apache POI 在后台通过代码生成 word 文档:2.使用模板生成 word 文档.第二种方法比较简单, ...

最新文章

  1. 收藏 | 机器学习防止模型过拟合
  2. python绘制曲线图-python绘制多个曲线的折线图
  3. 理解js中的this指向以及call,apply,bind方法
  4. 改变textFiled中placeholder的字体颜色的方法以及不想光标在textView的最左边设置方法...
  5. DGL教程【二】如何通过DGL表示一个Graph
  6. 一.Spring框架基础
  7. oracle trace发起用户,Oracle 使用TRACE进行SQL性能分析
  8. 网管型光纤收发器产品功能特性详解
  9. bi导入数据失败 power_主机数据库平台迁移 6 个典型问题
  10. drupal ajax json异步调用
  11. Unix/Mac系统下的文件在Windows里打开的话,所有文字会变成一行——怎么将Unix/Mac系统下的文件转换到Windows系统下
  12. 我开发的内部ORM(一)数据库组件
  13. 电力系统——基于10机39节点的电力系统仿真(Matlab)
  14. java中的加加++的疑惑?
  15. 【自动化】Python脚本selenium库完成自动创建汇联易账号
  16. DIY LDAC蓝牙接收器(二)硬件调试篇
  17. java图片缩小算法_图片缩小尺寸算法
  18. 以太坊地址检测算法golang实现
  19. 基于全球模式比较计划CMIP6与区域气候-化学耦合模式 WRF-Chem 的未来大气污染变化模拟
  20. 人物-作家-卡耐基:戴尔·卡耐基

热门文章

  1. Fork Join 框架的用途
  2. 收藏推荐| MacOS取证入门直播课听课笔记
  3. Mac 安装 adb 以及错误解决
  4. 看完通辽可汗小约翰之后应该掌握的英语词汇 01 外交类
  5. PPT设计的四大基本原则(重复)
  6. java给教师排课模块,java选排课系统
  7. 大家应该都用过SVN,多个小组开发时,分小组提交代码,可是有特殊情况的,小组要穿插提交增量文件,该怎么做呢?SVN补丁是一种能导出变更增量的方法。...
  8. 如何调出天正8.2中上部的工具条
  9. fatal error LNK1169: one or more multiply defined symbols found 终极解决方案
  10. php新浪微博 登录接口文档,新浪微博的账号登录及PHP api操作