1、Maven依赖
<dependency> <groupId>org.freemarker</groupId> <artifactId>freemarker</artifactId> <version>2.3.23</version> </dependency> <dependency> <groupId>com.itextpdf</groupId> <artifactId>itextpdf</artifactId> <version>5.4.2</version> </dependency> <dependency> <groupId>com.itextpdf.tool</groupId> <artifactId>xmlworker</artifactId> <version>5.4.1</version> </dependency> <dependency> <groupId>com.itextpdf</groupId> <artifactId>itext-asian</artifactId> <version>5.2.0</version> </dependency> <dependency> <groupId>org.xhtmlrenderer</groupId> <artifactId>flying-saucer-pdf</artifactId> <version>9.0.3</version> </dependency>
2、pdfTemplate.ftl模板
<!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> <style type="text/css"> body { font-family: SimSun; } @page{size:A3 } .pianyi{ display:block; font-family:SimSun; padding-left:15px; padding-right:15px; -webkit-margin-after:16px; -webkit-margin-before:16px; -webkit-margin-end:0px; -webkit-margin-start:0px; } .textSpan { padding-left: 15px; padding-right: 15px; line-height: 27px; } </style> </head> <body> <h3 style="text-align: center;">电子授权书</h3> <p class="pianyi">被授权人名称</p> <span class="textSpan">授权人(申请人)姓名: ${name}</span><br></br> <span class="textSpan">身份证号: ${idCardNo}</span><br></br> <span class="textSpan">授权协议生效日期: ${dateD} </span><br></br> <br/> <div style="word-wrap: break-word;word-break: break-all;overflow: hidden; "> ${content} </div> <div style="padding-left:15px;padding-right:15px;">签名处:</div> </body> </html>
3、创建GeneratePdf类
package com.wap.common; import com.itextpdf.text.pdf.BaseFont; import freemarker.template.Configuration; import freemarker.template.Template; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.xhtmlrenderer.pdf.ITextRenderer; import java.io.File; import java.io.FileOutputStream; import java.io.OutputStream; import java.io.StringWriter; import java.util.HashMap; import java.util.Locale; import java.util.Map; /** * 生成Pdf * Created by dgl on 2018/8/6. */ public class GeneratePdf implements Runnable { private static Logger logger = LoggerFactory.getLogger(GeneratePdf.class); private String webPath; //= PathUtil.getPath();//web根目录 /** * 指定FreeMarker模板文件的位置 */ private String templatePath; /** * freeMarker模板文件名称 */ private static String templateFileName = "pdfTemplate.ftl"; /** * 图片路径 —— 默认是classpath下面的images文件夹 */ private static String imagePath = "/upload/"; /** * 指定编码 */ private static String encoding = "UTF-8"; /** * 字体 [宋体][simsun.ttc] [黑体][simhei.ttf] */ private String font; /** * 需要传入的数据 */ private Map<String, Object> dateMap; /** * 申请单号 */ private String applyFromCode; //上传的目录 /*private static String directory;*/ public GeneratePdf() { } public GeneratePdf(Map<String, Object> dateMap, String applyFromCode, String webPath) { this.dateMap = dateMap; this.applyFromCode = applyFromCode; this.webPath = webPath; this.templatePath = webPath + "/uf/template/"; this.font = templatePath + "/simsun/simsun.ttc"; } /** * 创建pdf * * @param data 变量数据 * @param applyFromCode 新pdf地址 (一个单号只能有一个PDF文件,所以就直接用申请单号来命名) * @throws Exception */ public Map<String, Object> createPdf(Map<String, Object> data, String applyFromCode) { Map<String, Object> map = new HashMap<>(); String message = ""; String detail = ""; Boolean status = true; String code = "200"; try { //创建文件 //生成的pdf文件路径 String newPdfPath = webPath + imagePath + applyFromCode + ".pdf"; // String newPdfPath = webPath + Setting.APPLY_FROM_PDF_PATH + "/" + applyFromCode + ".pdf"; File file = new File(newPdfPath); if (!file.getParentFile().exists()) { file.getParentFile().mkdirs(); } FileOutputStream out = new FileOutputStream(file); GeneratePdf pdf = new GeneratePdf(); pdf.createPDF(data, out); message = "创建成功"; //创建完成后的pdf文件所在地址 detail = newPdfPath; logger.info("创建基础PDF完成"); //线程休息 Thread.sleep(1000); out.close(); out.flush(); } catch (Exception e) { e.printStackTrace(); message = "创建pdf文件错误失败"; status = false; code = "5005"; detail = ""; logger.error("创建pdf文件错误" + e.getMessage()); } map.put("status", status); map.put("message", message); map.put("detail", detail); map.put("code", code); return map; } /** * 根据模板生成pdf * * @param data 传入到freemarker模板里的数据 * @param out 生成的pdf文件流 */ public void createPDF(Object data, OutputStream out) throws Exception { // 创建一个FreeMarker实例, 负责管理FreeMarker模板的Configuration实例 Configuration cfg = new Configuration(Configuration.DEFAULT_INCOMPATIBLE_IMPROVEMENTS); // 指定FreeMarker模板文件的位置 ITextRenderer renderer = new ITextRenderer(); try { cfg.setDirectoryForTemplateLoading(new File(templatePath)); // 设置 css中 的字体样式(暂时仅支持宋体和黑体) renderer.getFontResolver().addFont(font, BaseFont.IDENTITY_H, BaseFont.NOT_EMBEDDED); // 设置模板的编码格式 cfg.setEncoding(Locale.CHINA, encoding); // 获取模板文件 template.ftl Template template = cfg.getTemplate(templateFileName, encoding); StringWriter writer = new StringWriter(); // 将数据输出到html中 template.process(data, writer); writer.flush(); String html = writer.toString(); // 把html代码传入渲染器中 renderer.setDocumentFromString(html); // 解决图片的相对路径问题 ##必须在设置document后再设置图片路径,不然不起作用 // 如果使用绝对路径依然有问题,可以在路径前面加"file:/" renderer.layout(); renderer.createPDF(out, false); renderer.finishPDF(); out.close(); out.flush(); } catch (Exception e) { e.printStackTrace(); } finally { out.close(); } } @Override public void run() { logger.info("开始异步生成PDF文件"); createPdf(dateMap, applyFromCode); logger.info("异步生成PDF文件完成"); } public String getApplyFromCode() { return applyFromCode; } public void setApplyFromCode(String applyFromCode) { this.applyFromCode = applyFromCode; } }
4、方法调用
/*** * Pdf sftp上传服务器 * @param name 申请人名字 * @param idCardNo 申请人身份证号 * @param dateD 申请时间 * @param content 内容说明 * @param applyFromCode 申请单号 * @paramdirectory 服务器存储路径 */ public static void printPdf(String webPath, String name, String idCardNo, String dateD, String content, String applyFromCode) { HashMap<String, Object> map = new HashMap<String, Object>(); map.put("name", name); map.put("idCardNo", idCardNo); map.put("dateD", dateD); map.put("content", content); GeneratePdf s = new GeneratePdf(map, applyFromCode, webPath); s.run(); }