1、思路:先通过模板生成HTML文件 --> 再把HTML文件生成PDF
2、pom.xml,增加itext 和 freemaker 的依赖
<dependency>
<groupId>org.xhtmlrenderer</groupId>
<artifactId>flying-saucer-pdf-itext5</artifactId>
<version>9.1.6</version>
</dependency>
<dependency>
<groupId>org.freemarker</groupId>
<artifactId>freemarker</artifactId>
<version>${freemarker.version}</version>
<scope>system</scope>
<systemPath>${project.basedir}/src/main/webapp/WEB-INF/lib/freemarker-null-2.3.19.jar</systemPath>
</dependency>
3、编写工具类:
package com.jeecg.wpxx.util;
import com.itextpdf.text.DocumentException;
import com.itextpdf.text.pdf.BaseFont;
import freemarker.template.Configuration;
import freemarker.template.DefaultObjectWrapper;
import freemarker.template.Template;
import org.xhtmlrenderer.pdf.ITextRenderer;
import javax.servlet.http.HttpServletRequest;
import java.io.*;
import java.util.Map;
public class PdfUtilsPic {
private static Template getTemplate(String template_path, String templateFileName, HttpServletRequest request) {
Configuration configuration = new Configuration();
Template template = null;
try {
configuration.setDirectoryForTemplateLoading(new File(request.getSession().getServletContext().getRealPath("/")+"export/template"));
configuration.setObjectWrapper(new DefaultObjectWrapper());
configuration.setDefaultEncoding("UTF-8"); //设置编码格式
//模板文件
template = configuration.getTemplate(templateFileName );
} catch (IOException e) {
e.printStackTrace();
}
return template;
}
public static void genteratorFile(Map<String, Object> input, String template_path, String templateFileName, String savePath, String fileName,HttpServletRequest request) {
Template template = getTemplate(template_path, templateFileName,request);
File filePath = new File(savePath);
if (!filePath.exists()) {
filePath.mkdirs();
}
String filename = savePath + "\\" + fileName;
File file = new File(filename);
if (!file.exists()) {
file.delete();
}
Writer writer = null;
try {
writer = new OutputStreamWriter(new FileOutputStream(filename), "UTF-8");
template.process(input, writer);
} catch (Exception e) {
e.printStackTrace();
}
}
public static void pdfHandler(String htmFilePath, String pdfFilePath,String pdfFileName) throws DocumentException, IOException {
File htmFile = new File(htmFilePath);
File pdfFilePath1 = new File(pdfFilePath);
if (!pdfFilePath1.exists()) {
pdfFilePath1.mkdirs();
}
File pdfFile = new File(pdfFilePath + pdfFileName);
String url = htmFile.toURI().toURL().toString();
OutputStream os = new FileOutputStream(pdfFile);
ITextRenderer renderer = new ITextRenderer();
org.xhtmlrenderer.pdf.ITextFontResolver fontResolver = renderer.getFontResolver();
System.setProperty("javax.xml.transform.TransformerFactory", "com.sun.org.apache.xalan.internal.xsltc.trax.TransformerFactoryImpl");
renderer.setDocument(url);
try {
// 添加字体,这里的字体要跟模板里的一样
fontResolver.addFont("c:/Windows/Fonts/simsun.ttc", BaseFont.IDENTITY_H, BaseFont.NOT_EMBEDDED);
fontResolver.addFont("c:/Windows/Fonts/arial.ttf", BaseFont.IDENTITY_H, BaseFont.NOT_EMBEDDED);
} catch (com.itextpdf.text.DocumentException e) {
e.printStackTrace();
}
renderer.layout();
try {
renderer.createPDF(os);
if (htmFile.exists()){
htmFile.delete();
}
} catch (com.itextpdf.text.DocumentException e) {
e.printStackTrace();
}
os.close();
}
}
4、控制器生成:
// 生成数据
Map<String,Object> map = new HashMap<>();
map.put("fjname","门头沟");
map.put("ajmc",listbySql.get(0).getAjmc());
map.put("badw",listbySql.get(0).getSwdw());
map.put("wplist",listbySql);
map.put("year",split[0]);
map.put("month",split[1]);
map.put("day",split[2]);
String ajbh = listbySql.get(0).getAjbh();
/**
路径
pdfPath=D://main//pdf
htmlPath=D://main//html
mp4Path=D://main//mp4
*/
String realPath = request.getSession().getServletContext().getRealPath("/");
String htmlPath = ResourceUtil.getConfigByName("htmlPath");
String pdfPath = ResourceUtil.getConfigByName("pdfPath");
String mp4Path = ResourceUtil.getConfigByName("mp4Path");
String signPath = realPath+"\\signPdf\\";
PdfUtilsPic.genteratorFile(map,realPath+"export/template","yjd.ftl",htmlPath,"yjd.html",request);
try {
PdfUtilsPic.pdfHandler(htmlPath+"\\yjd.html",pdfPath+"\\",ajbh+".pdf");
} catch (DocumentException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
5、踩过的坑:
(1)、ftl模板里不能没有闭合标签,这个是必须的,所以的标签都必须有闭合。
(2)、注意字体,不然中文乱码,模板里的字体和生成PDF的字体要保持一致。
6、模板文件:ftl文件
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8"></meta>
<title></title>
<style type="text/css">
body {
text-align: center;
}
.tablex {
border: 1px solid black;
border-collapse: collapse;
width: 100%;
text-align: left;
margin: auto;
}
.tablex th,
.tablex td {
border: 1px solid black;
padding: 10px;
}
tr {
height: 50px;
}
.info {
width: 100%;
height: 50%;
display: flex;
justify-content: flex-start;
font-size: 16px;
}
.fon {
width: 100%;
font-size: 16px;
text-align: left;
margin: auto;
}
</style>
</head>
<!-- 这是字体,要和java生成PDF的工具类中的字体保持一致 -->
<body style="font-family: SimSun;">
<h1>${fjname}移交清单</h1><br/>
<table class="tablex">
<tr>
<td colspan="5">名称:${ajmc}</td>
</tr>
<tr>
<td colspan="5">部门:${badw}</td>
</tr>
<tr style="text-align: center;">
<td>编号</td>
<td>名称</td>
<td>数量</td>
<td>特征</td>
<td>备注</td>
</tr>
<#list wplist as wp>
<tr>
<td>${wp_index+1}</td> <!-- 序号。是循环的索引 -->
<td>${wp.wpmc}</td>
<td>${wp.wpsl}</td>
<td>${wp.wpms}</td>
<td>${wp.bz}</td>
</tr>
</#list>
<tr style="height: 200px;">
<td colspan="5">
<table style="width: 100%;height: 100%;border: 0px;">
<tr>
<td style="height: 100%;width: 50%;border: 0px;">
<div class="info">
保管人(签字)
<br/><br/><br/><br/><br/><br/>
${year} 年 ${month} 月 ${day} 日
</div>
</td>
<td style="height: 100%;width: 50%;border: 0px;">
<div class="info" style="justify-content: center;">
移交人(签字)
<br/><br/><br/><br/><br/><br/>
${year} 年 ${month} 月 ${day} 日
</div>
</td>
</tr>
</table>
</td>
</tr>
</table>
<div class="fon">本清单一式两份,部门留存。</div>
</body>
</html>