iText+freemarker 生成PDF

  • 生成样式图片
  • 模板地址
  • maven
  • PDF生成工具类
  • PDF生成辅助类
  • base64编码工具类
  • service方法调用
  • 总结

生成样式图片

模板地址

maven

     <!--PDF  start--><dependency><groupId>org.xhtmlrenderer</groupId><artifactId>flying-saucer-pdf</artifactId><version>9.1.5</version></dependency><dependency><groupId>org.xhtmlrenderer</groupId><artifactId>flying-saucer-pdf-itext5</artifactId><version>9.1.5</version></dependency><!--PDF  end--><!--freemarker--><dependency><groupId>org.freemarker</groupId><artifactId>freemarker</artifactId><version>2.3.26-incubating</version></dependency><!--条形码--><dependency><groupId>com.google.zxing</groupId><artifactId>javase</artifactId><version>3.3.3</version></dependency>

PDF生成工具类

import com.lowagie.text.DocumentException;
import freemarker.core.ParseException;
import freemarker.template.MalformedTemplateNameException;
import freemarker.template.TemplateException;
import freemarker.template.TemplateNotFoundException;
import org.xhtmlrenderer.pdf.ITextRenderer;import java.io.IOException;
import java.io.OutputStream;/*** @Description PDF生成工具类* @author GGBind* @date 2021/12/28/10:03*/
public class PdfUtils {/*** 生成PDF到输出流中(ServletOutputStream用于下载PDF)** @param ftlPath       ftl模板文件的路径(不含文件名)* @param ftlName       ftl模板文件的名称(不含路径)* @param imageDiskPath 如果PDF中要求图片,那么需要传入图片所在位置的磁盘路径* @param data          输入到FTL中的数据* @param out      HttpServletResponse* @return* @throws TemplateNotFoundException* @throws MalformedTemplateNameException* @throws ParseException* @throws IOException* @throws TemplateException* @throws DocumentException*/public static OutputStream generateToServletOutputStream(String ftlPath, String ftlName, String imageDiskPath, Object data, OutputStream out) throws IOException, TemplateException, DocumentException {PdfHelper pdfHelper = new PdfHelper();String html =  pdfHelper.getPdfContent(ftlPath, ftlName, data);ITextRenderer render = null;render = pdfHelper.getRender();render.setDocumentFromString(html);if (null != imageDiskPath && !"".equals(imageDiskPath)) {//html中如果有图片,图片的路径则使用这里设置的路径的相对路径,这个是作为根路径render.getSharedContext().setBaseURL("file:/" + imageDiskPath);}render.layout();render.createPDF(out);render.finishPDF();return out;}
}

PDF生成辅助类

package com.saicmotor.maxus.yuejin.partorder.common.util.pdfUtil;import com.lowagie.text.DocumentException;
import com.lowagie.text.pdf.BaseFont;
import freemarker.template.Configuration;
import freemarker.template.Template;
import freemarker.template.TemplateException;
import freemarker.template.Version;
import lombok.extern.slf4j.Slf4j;
import org.xhtmlrenderer.pdf.ITextRenderer;import javax.servlet.ServletOutputStream;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.io.StringWriter;
import java.util.Locale;/*** PDF生成辅助类* @author GGBind* @date 2022/2/09*/
@Slf4j
@SuppressWarnings("deprecation")
public class PdfHelper {public ITextRenderer getRender() throws DocumentException, IOException {ITextRenderer render = new ITextRenderer();//添加字体,以支持中文render.getFontResolver().addFont("/static/fonts/NSimSun.ttc", BaseFont.IDENTITY_H, BaseFont.NOT_EMBEDDED);return render;}/*** 获取要写入PDF的内容* @param ftlPath* @param ftlName* @param o* @return* @throws IOException* @throws TemplateException*/public String getPdfContent(String ftlPath, String ftlName, Object o) throws IOException, TemplateException {return useTemplate(ftlPath, ftlName, o);}/*** 使用freemarker得到html内容* @param ftlPath* @param ftlName* @param o* @return* @throws IOException* @throws TemplateException*/public String useTemplate(String ftlPath, String ftlName, Object o) throws IOException, TemplateException {String html = null;Template tpl = getFreemarkerConfig(ftlPath).getTemplate(ftlName);tpl.setEncoding("UTF-8");StringWriter writer = new StringWriter();tpl.process(o, writer);writer.flush();html = writer.toString();return html;}/*** 获取Freemarker配置** @param templatePath* @return* @throws IOException*/private Configuration getFreemarkerConfig(String templatePath) throws IOException {Version version = new Version("2.3.22");Configuration config = new Configuration(version);config.setClassLoaderForTemplateLoading(Thread.currentThread().getContextClassLoader(), "/templates");config.setEncoding(Locale.CHINA, "utf-8");return config;}/*** 获取类路径** @return*/public String getPath() {return PdfHelper.class.getResource("/").getPath().substring(1);}/*** 获取前端response的输出流* 并设置response 编码格式* @return 输出流out*/public ServletOutputStream setResponse(HttpServletResponse response, String Name) throws Exception{response.setContentType("application/pdf");response.setCharacterEncoding("utf-8");response.setHeader("Content-disposition", "attachment;filename="+ new String(Name.getBytes("utf-8"), "ISO8859-1") + ".pdf");ServletOutputStream out = response.getOutputStream();return out;}}

base64编码工具类

import com.google.zxing.BarcodeFormat;
import com.google.zxing.MultiFormatWriter;
import com.google.zxing.client.j2se.MatrixToImageWriter;
import com.google.zxing.common.BitMatrix;
import lombok.extern.slf4j.Slf4j;
import sun.misc.BASE64Encoder;import javax.imageio.ImageIO;
import java.awt.image.BufferedImage;
import java.io.ByteArrayOutputStream;/*** @Description* @Author GGBond* @Date 2022/2/14*/
@Slf4j
public class BarcodeUtil {/*** 给前端产生一个条形码** @param number 编码* @param width  宽度* @param height 高度*/public static String getCode(String number, Integer width, Integer height) {// 生成条形码BufferedImage image = getBarCode(number, width, height);// 使用流的方式ByteArrayOutputStream out = new ByteArrayOutputStream();try {ImageIO.write(image, "png", out);} catch (Exception e) {log.info("generate code error! error message:{}", "出现问题!");e.printStackTrace();}// 将流转成数组byte[] bytes = out.toByteArray();BASE64Encoder encoder = new BASE64Encoder();// 把生成的编码返回去return  encoder.encodeBuffer(bytes).trim();}/*** 产生条形码的方法** @param number 编码* @param width  宽度* @param height 高度*/public static BufferedImage getBarCode(String number, Integer width, Integer height) {try {BitMatrix bitMatrix = new MultiFormatWriter().encode(number, BarcodeFormat.CODE_128, width, height);return MatrixToImageWriter.toBufferedImage(bitMatrix);} catch (Exception e) {e.printStackTrace();}return null;}/*** 调用测试*/public static void main(String[] args) {String code = getCode("1120220202", 50, 50);System.out.println(code);}
}

service方法调用

PdfHelper pdfHelper = new PdfHelper();List<StockCheckDetailPdf> lists = baseMapper.getStockCheckDetailPdf(dto);ServletOutputStream out = pdfHelper.setResponse(response, "盘点单据");String path = pdfHelper.getPath();Map<String,Object> map = new HashMap<>(16);map.put("list",lists);String code = BarcodeUtil.getCode(dto.getInventoryNumber(), 80, 20);map.put("picture", code);map.put("builder",builder.toString());map.put("inWarehouse",documentCounting.getInWarehouse());map.put("printDate",String.valueOf(DateUtil.getCurrentDate()));//这里我们需要将生成的base64图片编码传到工具类里,进行单独设置,静态图片也是如此PdfUtils.generateToServletOutputStream(path, "/documentCountingPDF.ftl", code, map, out);out.flush();
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN"  "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
<html>
<head><meta http-equiv="Content-Type" content="text/html; charset=utf-8"/><title>PDF</title><style>/*设置编码格式*/body {font-family: NSimSun}/*设置纸张大小*/@page {size: a4}@media print {div.header-right {display: block;position: running(header-right);}/*设置每页结束的是表格,还是图片,还是其他的*//*img{page-break-inside:avoid;}*/table {page-break-inside: avoid;}}* {margin: 0;padding: 0;box-sizing: border-box;}section {display: block;margin: 20px 10px;}.preface p {line-height: 30px;}section > table {table-layout: fixed;width: 100%;margin: 20px 0px;text-align:center;word-wrap:break-word;border-collapse: collapse;border-style: solid;border-width: 1px 0px 0px 1px;}section table td {padding: 5px 0px;border-style: solid;border-width: 0px 1px 1px 0px;margin: 0;padding: 0;}.center {width: 5.8%;}.part {width: 159.1px;word-break: keep-all;white-space: nowrap;}</style>
</head>
<body>
<section><#--该list 是由service层的map对应,数据使用占位符去匹配${}--><#list list as item><#if item_index % 14 == 0 || item_index == 0><table cellSpacing="0" cellpadding="0" border="1" width="650px" align="center" ><colgroup><col class="center"></col><col class="part"></col><col class="part"></col><col class="center"></col><col class="center"></col><col class="center"></col><col class="center"></col><col class="center"></col><col class="center"></col><col class="center"></col><col class="center"></col><col class="center"></col><col class="center"></col><col class="center"></col><col class="center"></col><col style="width: 70px;word-break: keep-all;white-space: nowrap"></col></colgroup></#if><#if item_index == 0><tr style="width: 100%;"><td class="center" colspan="2"><img src="data:image/png;base64,${picture}"/></td><td class="center" colspan="7"><h4>实物盘点记录表</h4></td><td class="center" colspan="7"><h1>${builder}</h1></td></tr><tr style="width: 100%;"><td class="center" colspan="4">填报单位:</td><td class="center" colspan="2">存货类别:</td><td class="center" colspan="9">仓库名称(代码): ${inWarehouse}</td><td style="word-break: keep-all;white-space: nowrap;">${printDate}</td></tr></#if><#if item_index % 14 == 0 || item_index == 0><tr style="width: 100%;"><td class="center" rowspan="2">序号</td><td class="part" rowspan="2">件号</td><td class="part" rowspan="2">名称</td><td class="center" rowspan="2">规格</td><td class="center" rowspan="2">项目类</td><td class="center" rowspan="2">计量单位</td><td class="center" rowspan="2">外借量</td><td class="center" rowspan="2">库位</td><td class="center" rowspan="2">合计</td><td class="center" rowspan="2">货位</td><td class="center" colspan="3">实盘数量</td><td class="center" rowspan="2">盘点人</td><td class="center" rowspan="2">监盘人</td><td class="center" rowspan="2">备注</td></tr><tr style="width: 100%;"><td class="center">合计</td><td class="center">企业库存</td><td class="center">供应商库存</td></tr></#if><tr style="width: 100%;"><td class="center">${item_index +1}</td><td class="part">${item.accessoryItemNo}</td><td class="part"><#if item.partsChineseName?length < 8 >${item.partsChineseName}<#else>${item.partsChineseName?substring(0,7)}</#if></td><td class="center">&nbsp;&nbsp;</td><td class="center">&nbsp;&nbsp;</td><td class="center">${item.unit}</td><td class="center">${item.lendingVolume?default(0)}</td><td class="center"><#if item.atWarehouse?exists>${item.atWarehouse!}</#if></td><td class="center">&nbsp;&nbsp;</td><td class="center">&nbsp;&nbsp;</td><td class="center">${item.theoreticalInventory}</td><td class="center">${(item.theoreticalInventory?default(0)) - (item.lendingVolume?default(0))}</td><td class="center">&nbsp;&nbsp;</td><td class="center">&nbsp;&nbsp;</td><td class="center">&nbsp;&nbsp;</td><td class="center"><#if item.remark?exists>${item.remark!}</#if></td></tr><#--用来判断每页展示多少条数据,最后需要加上 “table” 标签--><#if (item_index+1) % 14 == 0 || (item_index+1) == list?size></table></#if></#list>
</section>
</body>
</html>

总结

需要注意的是:当前此方法不能控制表格中一行数据变长,自动向下延申后,每页的格式问题;

例如: 当前页14条数据占满本页后,如果表格中字段较长,14行表格会向下延申到第二页,甚至第三页,才会进行下一个表格的展示;目前本方案解决办法是将一页展示的数量变小了,给预留出足够的空白页让其展示;目前还在寻找方法中

目前为止如果表格不够复杂,是够用的,其他的问题暂时还没碰到;

iText+freemarker 生成PDF 使用ftl模板相关推荐

  1. HTML生成PDF模板(Java iText+FreeMarker生成PDF(HTML转PDF))

    Java iText+FreeMarker生成PDF(HTML转PDF) 1.背景 在某些业务场景中,需要提供相关的电子凭证,比如网银/支付宝中转账的电子回单,签约的电子合同等.方便用户查看,下载,打 ...

  2. Itext生成pdf文件,itext+Freemarker生成pdf,(中文空白解决)

    来源:https://my.oschina.net/lujianing/blog/894365 1.背景 在某些业务场景中,需要提供相关的电子凭证,比如网银/支付宝中转账的电子回单,签约的电子合同等. ...

  3. [itext]Java生成PDF文件

    一.前言 最近在做也导出试卷的功能,刚开始是导出为doc,可是导出来格式都有变化,最后说直接将word转为pdf,可是各种不稳定,各种报错.最后想到直接将文件写入pdf(参考:http://www.c ...

  4. Itext 7 生成pdf带有背景图

    Itext 7 生成pdf带有背景图并下载PDF到本地 引入jar包 <dependency><groupId>com.itextpdf</groupId>< ...

  5. 使用IText5+Freemarker生成PDF(模板可以使用CCS3分页效果)

    iText介绍 iText是著名的开放源码的站点sourceforge一个项目,是用于生成PDF文档的一个java类库.通过iText不仅可以生成PDF或rtf的文档,而且可以将XML.Html文件转 ...

  6. java生成pdf盖章合同_Java中使用 FreeMarker 生成pdf盖章合同文件

    [实例简介] 1.html模板+model数据,通过freemarker进行渲染,便于维护和修改 2.渲染后的html流,可通过Flying Saucer组件生成pdf文件流,或者生成pdf后再转成j ...

  7. Java通过freemarker生成pdf文件并盖章

    Java代码生成pdf回执文件,直接上代码: package com.pdf;import java.io.BufferedWriter; import java.io.File; import ja ...

  8. Velocity+IText+Flying-saucer生成pdf文件

    这篇文章比较长,包括三个模块的内容: 用到的相关jar包及其版本号 根据velocity模板生成html文件方法 根据html文件生成pdf文件方法 如果你是其它方法已经生成了html模板,则直接参考 ...

  9. 2021-11-11 itext html生成pdf 内容过长分页问题

    项目场景: 在公司用itext 生成html 并保存为PDF,html中有个div很长很长,导致生成完PDF之后,页面有大量空白 html样式: 生成PDF之后: 解决方案: 计算好一整页有多少行数据 ...

最新文章

  1. 登录账号 npm_自定义npm 及问题整理
  2. 第1章 游戏之乐——构造数独
  3. 推荐阅读20101115
  4. leetcode 41. First Missing Positive 1
  5. nn.functional 和 nn.Module入门讲解
  6. 在JSP中动态生成随机验证码,登录时后台校验验证码,以及如何避免同一个验证码被重复提交爆破密码...
  7. U盘安装系统时黑屏! 无法进入解决办法
  8. SQL对某个字段分组并加序号
  9. MATLAB中saveas函数使用
  10. 【MySQL】Mcafee审计插件
  11. win10u盘被写保护怎么解除_win10系统中u盘被写保护怎么解除
  12. android改手机名称,如何修改手机 App 的名称?「App Name Editor」可轻松自订(Android)...
  13. Delphi FireDAC SQLite “database is locked“ 解决办法
  14. 初中几何知识复习,已知直角三角形角度和邻边长求对边长
  15. Silane-PEG-NH2 氨基聚乙二醇硅烷 NH2-PEG-Silane结构式
  16. 女程序员,作程序员还是作女人?
  17. Java基础 DAY13
  18. 《有限与无限的游戏》第三章 我是自己的天才:经典摘抄(1)
  19. 实拍:南非之三-开普敦的“渔人码头”,维
  20. 降维打击!北大「韦神」一夜拿下困住6名博士4个月的难题

热门文章

  1. 爬虫回响521_爬虫遇到521错误怎么办
  2. LeetCode521
  3. mac 上配置 git send-email
  4. PR和AE打不开的进来看看
  5. 粤嵌Gec6818---小项目功能实现(RFID+图片显示+音乐+视频)
  6. proftpd安装及基本配置
  7. oracle rebalance参数,Oracle10g ASM Auto IO Rebalance-power
  8. 【Linux】面试题4.5
  9. 茴香豆的“茴”字有三种写法
  10. xlwt 写入 Excel