ftl转pdf及问题集锦
这是一个令人悲伤的问题,本人在网上大量查找资料,总是有这样那样的问题导致不能转换成功
引入的maven jar包如下
<dependency> <groupId>com.itextpdf</groupId> <artifactId>itextpdf</artifactId> <version>5.4.3</version> </dependency> <dependency> <groupId>com.itextpdf.tool</groupId> <artifactId>xmlworker</artifactId> <version>5.5.5</version> </dependency> <dependency> <groupId>com.itextpdf</groupId> <artifactId>itext-asian</artifactId> <version>5.2.0</version> </dependency> <dependency> <groupId>org.xhtmlrenderer</groupId> <artifactId>core-renderer</artifactId> <version>R8</version> </dependency>
参考了很多资料,我选择的是 https://blog.csdn.net/NetSnake_/article/details/77161106 作为参考
@RequestMapping("/printingcontractNew") public void printingcontractNew( HttpServletResponse response,Long orderId,HttpServletRequest request) throws Exception { Map<String, Object> map = new HashMap<String, Object>(); map.put("orderContract", order); map.put("orderinformation", orderinformation); //输入需要传输的数据 try { ByteArrayOutputStream baos = FtlToPdf1.createPDF(request, "PrintingContract.ftl", map); //"PrintingContract.ftl"为自己的ftl能展示的(注意结构必须严谨) System.out.println(baos); //设置response文件头 FtlToPdf1.renderPdf(response, baos.toByteArray(), "789"); //789 为输出pdf的名字可以自己命名 } catch (Exception e) { throw new Exception(e); } /* ftlTOPDF.FTL2PDF(srcPath, destPath, map);*/ }
package com.ningpai.site.pdf; /*import com.lowagie.text.pdf.BaseFont;*/ import com.itextpdf.text.pdf.BaseFont; import com.itextpdf.text.pdf.PdfWriter; import com.itextpdf.tool.xml.XMLWorkerHelper; import freemarker.template.Configuration; import freemarker.template.Template; import org.xhtmlrenderer.pdf.ITextFontResolver; import org.xhtmlrenderer.pdf.ITextRenderer; import com.itextpdf.text.Font; import com.itextpdf.text.Document; import com.itextpdf.text.Paragraph; /* import org.xhtmlrenderer.pdf.ITextFontResolver; import org.xhtmlrenderer.pdf.ITextRenderer; */ import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; import java.io.*; import java.nio.charset.Charset; import java.util.HashMap; import java.util.Locale; import java.util.Map; /** * Created by Administrator on 2018-5-19. */ public class FtlToPdf1 { /** * 生成PDF文件流 * @param request * @param ftlName 文件名称 * @param root 数据 * @return ByteArrayOutputStream * @throws Exception */ public static ByteArrayOutputStream createPDF(HttpServletRequest request, String ftlName, Object root) throws Exception { String basePath = request.getSession().getServletContext().getRealPath("/");//绝对路径 Configuration cfg = new Configuration(); try { cfg.setLocale(Locale.CHINA); cfg.setEncoding(Locale.CHINA, "UTF-8"); //设置编码 cfg.setDefaultEncoding("UTF-8"); //设置模板路径 cfg.setDirectoryForTemplateLoading(new File(basePath + "view/contract/")); //获取模板 Template template = cfg.getTemplate(ftlName); template.setEncoding("UTF-8"); ITextRenderer iTextRenderer = new ITextRenderer(); //设置字体 ITextFontResolver fontResolver = iTextRenderer.getFontResolver(); fontResolver.addFont(basePath + "view/contract/simsun.ttf", BaseFont.IDENTITY_H, BaseFont.NOT_EMBEDDED); "view/contract/simsun.ttf" 为下载的字体将其放入程序中的位置 Writer writer = new StringWriter(); //数据填充模板 template.process(root, writer); //设置输出文件内容及路径 String str = writer.toString(); iTextRenderer.setDocumentFromString(str); iTextRenderer.getSharedContext().setBaseURL("file:/D:"); //图片共享路径file:/home/ddcj/ iTextRenderer.layout(); //生成PDF ByteArrayOutputStream baos = new ByteArrayOutputStream(); iTextRenderer.createPDF(baos); //这里会显示有乱码 , 但对最后输出结果没有影响 baos.close(); return baos; } catch(Exception e) { throw new Exception(e); } } //此方法主要是设置文件头,并把文件作为附件下载 public static void renderPdf(HttpServletResponse response, final byte[] bytes, final String filename) { setFileDownloadHeader(response, filename, ".pdf"); if (null != bytes) { try { response.getOutputStream().write(bytes); response.getOutputStream().flush(); } catch (IOException e) { throw new IllegalArgumentException(e); } } } /** * 设置让浏览器弹出下载对话框的Header. * @param fileName 下载后的文件名. */ public static void setFileDownloadHeader(HttpServletResponse response, String fileName, String fileType) { try { // 中文文件名支持 String encodedfileName = new String(fileName.getBytes("GBK"), "ISO8859-1"); response.setHeader("Content-Disposition", "attachment; filename=\"" + encodedfileName + fileType + "\""); } catch (UnsupportedEncodingException e) { } } }
效果图如下:
点击打印
打开后
格式有点丑,还没开始修改...
问题集锦:
1.org.xhtmlrenderer.util.XRRuntimeException: Can't load the XML resource (using TRaX transformer). org.xml.sax.SAXParseException; lineNumber: 167; columnNumber: 44; 元素类型 "td" 必须由匹配的结束标记 "</td>" 终止。
报错的代码如下:
<tr> <td class="product_table_th">供方:xxx</br>地址:xxx</br>电话:028-3xxxx59</br>传真:028-xxxxx909</br> 开户银行:中国建设xxx分行</br>账号:5100 xxxx xxxx xxx1 0200 </td> <td class="product_table_th">需方:${orderinformation.invoiceCompanyName}</br>地址:${orderinformation.invoiceSite} </br> 电话:${orderinformation.invoicePhoneNumber}</br>传真:</br> 开户银行:${orderinformation.invoiceDepositBank}</br>账号:${orderinformation.invoiceBankAccount} </td> </tr>
想做成的效果
经过多次查找,发现没什么问题;页面也能正常的显示,但就是会再转pdf时报错
最后无意间修改解决了问题
<tr> <td class="product_table_th">供方:四川xxxx有限公司<br></br>地址:xxxx开发区<br></br>电话:028-xxxx59<br></br>传真:028-3xxxx09<br></br> 开户银行:中国xxx分行<br></br>账号:5100 xxxxx 0200 </td> <td class="product_table_th">需方:${orderinformation.invoiceCompanyName}<br></br>地址:${orderinformation.invoiceSite} <br></br> 电话:${orderinformation.invoicePhoneNumber}<br></br>传真:<br></br> 开户银行:${orderinformation.invoiceDepositBank}<br></br>账号:${orderinformation.invoiceBankAccount} </td> </tr>
重点为<br></br> 因为itex转pdf是非常严谨的必须有开头和结尾
2.org.xhtmlrenderer.util.XRRuntimeException: Can't load the XML resource (using TRaX transformer). org.xml.sax.SAXParseException; lineNumber: 89; columnNumber: 45; 元素类型 "td" 必须后跟属性规范 ">" 或 "/>"。
报错代码为
<tr> <td class="product_table_th">备注</td> <td class="product_table_th"colspan="5"> ${orderinformation.customerRemark} </td> </tr>
原因居然是
这。。。尼....果然严谨
3. 本因分开的结果没有分开对应显示
错误代码
<#list orderContract as good> <thead align="center"> <tr> <td class="product_table_th"><span>${good.goodsInfoName}</span></td> <td class="product_table_th"><span>${good.goodsInfoNum}</span></td> <td class="product_table_th"><span>件</span></td> <td class="product_table_th"><span>${good.goodsInfoPrice}</span></td> <td class="product_table_th"><span>${good.goodsInfoSumPrice}</span></td> </tr> </thead> </#list>
原因:加入了<thead align="center">属性,,,注释掉就好
4.只显示数字和英文 , 中文字符不显示问题
在网上查了很多,各方面的问题解决方法都有
我的问题是
<?xml version="1.0" encoding="UTF-8"?> <!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"></meta> <meta name="renderer" content="webkit"></meta> </head> <body style="font-size:12.0pt; font-family: SimSun; background: none;margin-left: auto;margin-right: auto">
<table.....>
...
主要是这个 <body style="font-size:12.0pt; font-family: SimSun; background: none;margin-left: auto;margin-right: auto"> 加上就好了