最近项目中遇到要用html生成pdf文件的需求,一开始研究了下前端插件jspdf,使用h5 canvas绘图生成图片,再把图片生成pdf文件,遇到了各种各样的问题,生成的pdf文件达到20多M,height超过5000浏览器就崩溃,有兴趣的童鞋可以尝试一下,该方案LZ最终放弃了。
接着开始尝试服务端生成,使用freemaker模板生成静态html文件,通过iext生成pdf,网上很多关于renderer.setDocument(dom,null)的用法,LZ尝试后发现效率奇低,最后放弃了,直接使用renderer.setDocumentFromString方法,要注意以下几点:
1、生成的html声明文件,xhtml部分要干掉,否则解析报错。
2、注意设置相对目录,一定要物理绝对目录,否者css和img文件就找不到了。
3、生成pdf时中文的问题,就是要加载字体文件simsun.ttc,这个网上解决方案不少,不做赘述,注意html加上样式。
<style> body{ font-family: SimSun; } </style>
public void exportPDF() throws Exception { OutputStream os = null; String htmlStr; Map<String, Object> params = new HashMap<String, Object>(); Map data = new HashMap(); try { /** xxx数据生成逻辑 **/ data.put("projects",xxx); //通过freemaker模板生成html htmlStr = HtmlGenerator.generate("pdf.ftl", data); String appPath = getReq().getSession().getServletContext().getRealPath("/") + File.separator; ITextRenderer renderer = new ITextRenderer(); renderer.setDocumentFromString(htmlStr,"file:" + appPath); // 解决中文支持问题 ITextFontResolver fontResolver = renderer.getFontResolver(); fontResolver.addFont(appPath + "template" + File.separator +"simsun.ttc", BaseFont.IDENTITY_H, BaseFont.NOT_EMBEDDED); //生成pdf文件 getRes().setHeader("Content-disposition", "attachment;filename=" + URLEncoder.encode("测试", "UTF-8") + new Date().getTime() + ".pdf"); getRes().setContentType("application/pdf"); os = getRes().getOutputStream(); renderer.layout(); renderer.createPDF(os, true); os.flush(); } catch (Exception e) { e.printStackTrace(); }finally { if (null != os) { try { os.close(); } catch (IOException e) { e.printStackTrace(); } } } }
HtmlGenerator类,编码设置UTF-8,设置正确,不然有中文乱码问题。
package com.haziwang.rkhy.util; import java.io.BufferedWriter; import java.io.StringWriter; import java.util.Map; import freemarker.template.Configuration; import freemarker.template.Template; public class HtmlGenerator { /** * @param template * @param variables * @return * @throws Exception */ public static String generate(String template, Map params) throws Exception{ Configuration config = FreemarkerConfiguration.getConfiguation(); config.setDefaultEncoding("UTF-8"); Template tp = config.getTemplate(template); StringWriter stringWriter = new StringWriter(); BufferedWriter writer = new BufferedWriter(stringWriter); tp.setEncoding("UTF-8"); tp.process(params, writer); String htmlStr = stringWriter.toString(); writer.flush(); writer.close(); return htmlStr; } }
FreemarkerConfiguration类,设置ftl文件目录,相对于classes目录设置
package com.haziwang.rkhy.util; import freemarker.template.Configuration; public class FreemarkerConfiguration { private static Configuration config = null; /** * Static initialization. * * Initialize the configuration of Freemarker. */ static{ config = new Configuration(); config.setClassForTemplateLoading(FreemarkerConfiguration.class, "/../../template/"); config.setTemplateUpdateDelay(0); } public static Configuration getConfiguation(){ return config; } }
代码目录结构
maven引入jar包
<dependency> <artifactId> flying-saucer-pdf-itext5 </artifactId> <groupId> org.xhtmlrenderer </groupId> <version> 9.0.6 </version> </dependency> <dependency> <artifactId> freemarker </artifactId> <groupId> freemarker </groupId> <version> 2.3.8 </version> </dependency>