基于FreeMarker生成PDF文件组件

本文档介绍了如何利用FreeMarker模板引擎和相关组件从HTML生成PDF,包括技术组件的选择、目录结构规范、字体对应关系以及详细的开发步骤。通过此方法,可以简化批复单的生成过程,减少重复工作量。
摘要由CSDN通过智能技术生成

基于FreeMarker生成PDF文件组件

背景说明: 流程平台在很多流程场景中,存在下载批复单的场景,原老流程平台下载批复单均按照java代码,遵从 pdf 的 SDK 标准格式填充,代码依次根据逻辑填充,此方式会存在大量的冗余代码并且重复开发工作量较大.

解决方案: 为减少工作量,从Html生成pdf,可减少较多重复工作量,并且html可以给业务人员展示 生成后的批复单 样式,减少重复沟通的成本。

技术组件jar包

  • PDF组件包:itextpdf 5.5.13.3
  • 通过html生成pdf包:xmlworker 5.5.13.3
  • PDF中文支持包组件:itext-asian 5.2.0
  • 支持css样式渲染PDF组件:flying-saucer-pdf-itext5 9.1.22
  • 转换html为标准xhtml包:jtidy r938
  • freemarker模板引擎:freemarker 2.3.31
  • POM引用包:
 <!-- 通用生成PDF逻辑 -->
        <!-- pdf:start -->
        <!-- https://mvnrepository.com/artifact/com.itextpdf/itextpdf -->
        <dependency>
            <groupId>com.itextpdf</groupId>
            <artifactId>itextpdf</artifactId>
            <version>5.5.13.3</version>
        </dependency>
        <dependency>
            <groupId>com.itextpdf.tool</groupId>
            <artifactId>xmlworker</artifactId>
            <version>5.5.13.3</version>
        </dependency>
        <!-- 支持中文 -->
        <dependency>
            <groupId>com.itextpdf</groupId>
            <artifactId>itext-asian</artifactId>
            <version>5.2.0</version>
        </dependency>
        <!-- 支持css样式渲染 -->
        <dependency>
            <groupId>org.xhtmlrenderer</groupId>
            <artifactId>flying-saucer-pdf-itext5</artifactId>
            <version>9.1.22</version>
        </dependency>
        <!-- 转换html为标准xhtml包 -->
        <dependency>
            <groupId>net.sf.jtidy</groupId>
            <artifactId>jtidy</artifactId>
            <version>r938</version>
        </dependency>
        <!-- https://mvnrepository.com/artifact/org.freemarker/freemarker -->
        <dependency>
            <groupId>org.freemarker</groupId>
            <artifactId>freemarker</artifactId>
            <version>2.3.31</version>
        </dependency>
        <!-- pdf:end -->

模块目录规范

一、从html(即:ftl)生成pdf,html模板放在该目录: resouces/pdf_template
  • word转换为pdf网址:http://www.docpe.com/word/word-to-html.aspx
  • 字体在线转换工具:https://www.fontke.com/tool/convfont
二、 从html(即:ftl)生成pdf字体,放在该目录: resouces/pdf_ttc
  • TTF和TTC字体格式解释
  • 1) TTF(TrueType Font)是TrueType字体文件,由 Apple 和 Microsoft 共同推出的一种字体文件格式。
  • 2) TTC(TrueType Collection)是TrueType字体集成文件,亦称为字体集。 由 Microsoft 开发的一种新的字体格式标准,在同一文件结构中包含多个字体,以便更有效地共享轮廓数据,缩减字体文件大小。

字体对应关系 (使用规则,格式必须为.ttf/.ttc)

  • 字体目前是供html生成pdf中文字使用。[HTML中的ftl(freemarker)模板技术,遵循该语法]。
  • 可添加多个字体文件,注意说明标记(font-family必须与字体文件名保持一致,否则会导致中文不显示)
  • 新增字体后,需要新增字体引用方可在html中使用:
GeneratePdfUtil.generatePDF(String pdfUrl){
    //参数:simSunFilePath 字体绝对路径,BaseFont.IDENTITY_H, BaseFont.NOT_EMBEDDED 两个参数固定。
    fontResolver.addFont(simSunFilePath, BaseFont.IDENTITY_H, BaseFont.NOT_EMBEDDED);
}
  • 特别说明: ttf的文件名,必须与在flt中的文字font-family一致,否则不会显示文字
    (例如:字体文件为CHXBS.ttf(彩虹小标宋),html的style中的 font-family:CHXBS; 必须为“CHXBS”(区分大小写),否则中文字体不显示)
字体名称字体文件名HTML(即:ftl模板) 中文字体设置说明(style中设置)
宋体SimSun.ttcfont-family:SimSun;
彩虹小标宋CHXBS.ttffont-family:CHXBS;
微软雅黑YaHei.ttffont-family:YaHei;

代码开发帮助文档

resources/simple下为对pdf对于的template生成的文件pdf,可参考

  • 1)pdf-chxbs.html 为彩虹小标宋 字体生成的对应pdf文件:pdf-cgxbs.pdf
  • 2)pdf-simsun.html 为宋体 字体生成的对应pdf文件:pdf-simsun.pdf
  • 3)pdf-simple.html 为模拟流程平台的批复单 字体(彩虹小标宋+宋体)生成的对应pdf文件:pdf-simple.pdf

操作步骤如下:

一、在word中画出需要的模板,如示例:resources/sample/cp_tmp.docx
特别注意:word中仅支持三种字体“宋体”、“彩虹小标宋”、“微软雅黑”。
二、将编辑完成的word,上传至如下“网址”,转换为html文档。

word转换html网址:http://www.docpe.com/word/word-to-html.aspx

   上传网址word,转换为html文件,其中word的 输出值  使用占位符 ${}包含。
   例如:${XMMC}  ,表示 项目名称 信息
三、检查并编辑HTML调整格式规范。

特别注意:

  • 1、编辑生成的HTML代码必须 标签有闭合,即:
<div> </div> 成对出现,否则解析xml报错。
  • 2、font-family:检查,为固定的3中字体,否则生成pdf中文不显示。
  • 3、${}占位符检查,转换的html中会出现被 <> 标签隔开需要调整代码。
1、编辑html代码,将代码中如下内容替换为支持的文字格式,必须为如下写法,否则pdf转换文字不显示
| 宋体      | font-family:SimSun; 
| 彩虹小标宋 | font-family:CHXBS; 
| 微软雅黑   | font-family:YaHei; 

2、检查生成的HTML代码中所有的font-family,取值为 以上3中字体(必须检查font-family:SimSun; /font-family:CHXBS; / font-family:YaHei;)
3、排查生成的HTML代码中,存在${XXX}的占位符被HTML转换后,<span>隔开的情况,进行归整(特别注意成对标签闭合检查)
4、检查完成后,可打开html进行预览,给业务确认表单格式及样式。
四、HTML存在判断场景,可以使用freemaker标签进行判断即可。

freemaker标签语法(pdf-simple.html 中的“分管领导意见”有 示例代码 )

  • 基本语法请自行度娘
  • 如下为判断和相关迭代指令用法
  • a)判断指令
--  if elseif else
<#if key == 1>
-- key=1时显示
<#elseif key == 2>
-- key=2时显示
<#else>
-- 其他情况时显示
</#if>

-- switch case
<#switch key>
  <#case 1>
-- key=1时显示
      <#break>-- 有该标签时当key=1时不会判断下面其他条件 
  <#case 2>
-- key=2时显示
      <#break>
  <#default>
-- 其他情况时显示
</#switch>
  • b. 遍历指令
-- list遍历 list要遍历的集合,item为遍历出的单个数据 <#else>可选
<#list list as item>
 ${item} -- 获取单个数据展示
<#else>
-- 集合为空时显示
</#list>

 -- list遍历
  <#list list as item>
     ${item} <#sep>, </#sep> -- <#sep>可为每个遍历出的元素之前添加分割元素
  </#list>
  
  -- list遍历 
  <#list list as item>
     ${item}
     <#if item == "C">
        <#break> -- <#break>可在遍历过程中停止之后的遍历
  </#if>
  </#list>

  -- list遍历: 遍历项  索引(0开始)  行号(1开始)  单双行(odd/even)
  <#list list as item>
     ${item} ${item?index} ${item?counter} ${item?item_parity}
  </#list>
  
    -- map遍历
   <#list map?keys as key> 
   ${key}  ${map[key]}
   </#list>
五、java执行html转换pdf生成代码
  • 详见GeneratePdfUtil.main()
  • 通过html代码(即:freemaker标签语法) 生成pdf文件(实际为ftl文件,区别是改了后缀名,底层freemaker技术实现)
  • java调用代码:
        /**
         * 获取模板路径和所在dir目录
         */
        String tplNameSimple = "pdf-simple.html";
        String TEMPLATES_PATH = getResouceFLTDirPath(tplNameSimple);
        
        /**
         * 参数MAP,用于填充html中的变量
         */
        Map<String, Object> paramMap = new HashMap<String, Object>();
        paramMap.put("PFBH", "JXXT-PF-2022-01");
        //批复信息
        paramMap.put("DEPTNAME", "财富管理事业部");
        paramMap.put("CSKSRQ", "建信信托-私人银行家族信托单一信托1001号");
        paramMap.put("PFJG", "项目评审管理委员会");
        paramMap.put("PFRQ", "2022年01月01日");
        paramMap.put("PFYJ", "否决,项目存在风险xxx等");
        //项目信息
        paramMap.put("XMMC", "建信信托-私人银行家族信托单一信托1001号");
        paramMap.put("XMGM", "20000万元");
        paramMap.put("FYMC", "36个月");
        paramMap.put("XMLY", "建行推荐");
        paramMap.put("ZHRZCB", "1%-2%/年");
        paramMap.put("ZJYYFS", "(2015)*****字第0**20-1**0号用于xxx项目投资、境外投资等");
        //意见详情
        //是否显示分管领导意见 标记
        paramMap.put("FGYJ_ISSHOW", "false");
        paramMap.put("JLYJ", "同意,乐乐。2022年03月31日");
        paramMap.put("FZRYJ", "同意,芳芳。2016年10月31日 00时00分");
        paramMap.put("ZYYJ", "同意,木木。2016年10月31日 00时00分");
        paramMap.put("FGYJ", "同意,冬冬。2016年10月31日 00时00分");
        //业务部门最后署名信息
        paramMap.put("YWBM", "项目综合管理部");
        paramMap.put("PFRQ", "2022年12月31日");
        
        /**
         * ContractDynamicParam  构建生成pdf的代码,如下为传入参数:
         * TEMPLATES_PATH :模板所在目录,固定写法即可。
         * tplNameSimple : 模板文件名,为新增的模板文件名,带后缀.html
         * "E:\": 为pdf输出的目录,可动态获取存储到服务器。
         * "pdf-simple.pdf" 为生成的pdf名称,带后缀名。
         * paramMap :为生成的html占位符数据map
         */
        ContractDynamicParam xbsPararm = new ContractDynamicParam(TEMPLATES_PATH, tplNameSimple,
                "E:\", "pdf-simple.pdf", paramMap);
        GeneratePdfUtil.GenerateContract(xbsPararm);
        System.out.println("====生成pdf-simple 批复单 - PDF成功====");
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

施主、请留步。

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值