一、场景
在某些业务场景中,需要提供相关的电子凭证,比如网银/支付宝中转账的电子回单,签约的电子合同等。方便用户查看,下载,打印。目前常用的解决方案是,把相关数据信息,生成对应的pdf文件返回给用户。
二、IText5中文支持与iText-Html渲染
iText是著名的开放源码的站点sourceforge一个项目,是用于生成PDF文档的一个java类库。通过iText不仅可以生成PDF或rtf的文档,而且可以将XML、Html文件转化为PDF文件。iText默认是不支持中文的,因此需要添加对应的中文字体。
1、引入maven 依赖
<!--itext5-->
<dependency>
<groupId>com.itextpdf</groupId>
<artifactId>itextpdf</artifactId>
<version>5.5.13</version>
</dependency>
<!--freemarker模板引擎-->
<dependency>
<groupId>org.freemarker</groupId>
<artifactId>freemarker</artifactId>
<version>2.3.19</version>
</dependency>
<!--itext5中文支持与html渲染-->
<dependency>
<groupId>org.xhtmlrenderer</groupId>
<artifactId>flying-saucer-pdf-itext5</artifactId>
<version>9.1.7</version>
</dependency>
2、java代码
包结构如下:
代码部分:
package code; import com.itextpdf.text.pdf.BaseFont; import freemarker.template.Configuration; import freemarker.template.Template; import model.PDFBaseModel; import org.xhtmlrenderer.pdf.ITextFontResolver; import org.xhtmlrenderer.pdf.ITextRenderer; import java.io.*; public class JavaToPdfHtmlFreeMarker { private static String freeMarkerRender(PDFBaseModel data, String htmlTmp) { Writer out = new StringWriter(); try { InputStream fis = JavaToPdfHtmlFreeMarker.class.getResourceAsStream(htmlTmp); StringBuilder sb = new StringBuilder(); byte[] bytes = new byte[1024]; try { for (int n; (n = fis.read(bytes)) != -1; ) { sb.append(new String(bytes, 0, n, "UTF-8")); } } catch (IOException e) { e.printStackTrace(); } Template template = new Template("处方笺模板", new StringReader(sb.toString()), new Configuration()); template.setEncoding("UTF-8"); // 合并数据模型与模板 template.process(data, out); //将合并后的数据和模板写入到流中,这里使用的字符流 fis.close(); out.flush(); out.close(); return out.toString(); } catch (Exception e) { e.printStackTrace(); } return null; } public static void createPdf(PdfType type, PDFBaseModel data, OutputStream os) throws Exception { String template = null; String font = null; switch (type) { case CF: template = "/cf/prescription.html"; font = "/cf/simsun.ttc"; break; default: break; } String content = freeMarkerRender(data, template); ITextRenderer render = new ITextRenderer(); ITextFontResolver fontResolver = render.getFontResolver(); fontResolver.addFont(font, BaseFont.IDENTITY_H, BaseFont.NOT_EMBEDDED); // 解析html生成pdf render.setDocumentFromString(content); render.layout(); render.createPDF(os); } public static void createPdf(String url, String fontPath, OutputStream os) throws Exception { ITextRenderer render = new ITextRenderer(); ITextFontResolver fontResolver = render.getFontResolver(); fontResolver.addFont(fontPath, BaseFont.IDENTITY_H, BaseFont.NOT_EMBEDDED); render.setDocument(url); render.layout(); render.createPDF(os); }
//模板生成图片 private static void convertHtmlToImage(String html, int width, int height, OutputStream out) throws Exception { StringReader sr = new StringReader(html); InputSource is = new InputSource(sr); DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance(); DocumentBuilder builder = factory.newDocumentBuilder(); org.w3c.dom.Document parse = builder.parse(is); Java2DRenderer renderer = new Java2DRenderer(parse, width, height); BufferedImage img = renderer.getImage(); FSImageWriter imageWriter = FSImageWriter.newJpegWriter(0.9f); imageWriter.write(img, out); }}
3、模板部分
1、freemarker 对html格式有严格标准,标签必须有对应的闭合;
2、itext5支持中文还需要html模板部分添加如下代码。
body {
font-family: SimSun;
}
最后打包成jar就可以了,以后可以根据需求添加相应的模板html即可。