最近遇到一个需求,需要使用Java生成PDF文件,网上的资料很杂乱,故整理记录一下
首先引入pom依赖
<!-- pdf:start -->
<dependency>
<groupId>com.itextpdf</groupId>
<artifactId>itextpdf</artifactId>
<version>5.5.11</version>
</dependency>
<dependency>
<groupId>com.itextpdf.tool</groupId>
<artifactId>xmlworker</artifactId>
<version>5.5.11</version>
</dependency>
<!-- 支持中文 -->
<dependency>
<groupId>com.itextpdf</groupId>
<artifactId>itext-asian</artifactId>
<version>5.2.0</version>
</dependency>
<!-- 支持css样式渲染 -->
<dependency>
<groupId>org.xhtmlrenderer</groupId>
<artifactId>flying-saucer-pdf-itext5</artifactId>
<version>9.1.16</version>
</dependency>
<!-- 转换html为标准xhtml包 -->
<dependency>
<groupId>net.sf.jtidy</groupId>
<artifactId>jtidy</artifactId>
<version>r938</version>
</dependency>
<!-- pdf:end -->
将生成代码PDF的工具类放入项目中
package com.seezoon.admin.framework.utils;
import com.itextpdf.text.pdf.BaseFont;
import com.seezoon.admin.framework.utils.bean.ContractDynamicParam;
import freemarker.template.Configuration;
import freemarker.template.Template;
import org.xhtmlrenderer.pdf.ITextRenderer;
import javax.servlet.http.HttpServletResponse;
import java.io.*;
import java.util.Map;
/**
* @Description: 生成PDF合同工具类
* @author liguodong
* @date 2022年3月6日 下午5:19:32
*/
public class GeneratePdfUtil {
//private static final String TEMPORARY_CONTRACT_HTML = "E:\\workspace\\dytc\\dytc\\seezoon-admin-server\\src\\main\\resources\\contract\\temporary.html";// 临时HTML合同,用于转PDF格式
private static final String TEMPORARY_CONTRACT_HTML = "/data/file/contract/temporary.html";
//private static final String SIMSUM_FILE = "E:\\workspace\\dytc\\dytc\\seezoon-admin-server\\src\\main\\resources\\common\\simsun.ttc";// 添加字体,解决中文支持问题
private static final String SIMSUM_FILE = "/data/file/common/simsun.ttc";
public static String GenerateContract(ContractDynamicParam param) throws Exception {
// 生成html合同
generateHTML(param.getTemplatePath(), param.getTemplateName(), param.getContractParam());
// 根据html合同生成pdf合同
generatePDF(param.getContractPath() + param.getContractName());
// 删除临时html格式合同
removeFile(TEMPORARY_CONTRACT_HTML);
return param.getContractPath() + param.getContractName();
}
/**
* @Description 生成html格式合同
*/
private static void generateHTML(String templatePath, String templateName, Map<String, Object> paramMap) throws Exception {
Configuration cfg = new Configuration();
cfg.setDefaultEncoding("UTF-8");
/**
* 1.setClassForTemplateLoading(this.getClass(), "/HttpWeb");
* 基于类路径,HttpWeb包下的framemaker.ftl文件
* 2.setDirectoryForTemplateLoading(new File("/template"));
* 基于文件系统,template目录下的文件
* 3.setServletContextForTemplateLoading(request.getSession().getServletContext(), "/template");
* 基于Servlet Context,指的是基于WebRoot下的template下的framemaker.ftl文件
*/
cfg.setDirectoryForTemplateLoading(new File(templatePath));
// templateName.ftl为要装载的模板
Template template = cfg.getTemplate(templateName);
File outHtmFile = new File(TEMPORARY_CONTRACT_HTML);
Writer out = new BufferedWriter(new OutputStreamWriter(new FileOutputStream(outHtmFile)));
// 将参数输出到模版,并操作到HTML上
template.process(paramMap, out);
out.close();
}
/**
* @Description 根据html生成pdf格式合同
*/
private static void generatePDF(String pdfUrl) throws Exception {
File htmFile = new File(TEMPORARY_CONTRACT_HTML);
File pdfFile = new File(pdfUrl);
System.out.println(pdfUrl);
String url = htmFile.toURI().toURL().toString();
OutputStream os = new FileOutputStream(pdfFile);
ITextRenderer renderer = new ITextRenderer();
renderer.setDocument(url);
org.xhtmlrenderer.pdf.ITextFontResolver fontResolver = renderer.getFontResolver();
// 解决中文支持问题
fontResolver.addFont(SIMSUM_FILE, BaseFont.IDENTITY_H, BaseFont.NOT_EMBEDDED);
renderer.layout();
renderer.createPDF(os);
os.close();
}
/**
* @Description 移除文件
*/
private static void removeFile(String fileUrl) {
File file = new File(fileUrl);
file.delete();
}
public static void returnPdfStream(HttpServletResponse response, String pathName) throws Exception {
response.setContentType("application/pdf");
File file = new File(pathName);
if (file.exists()) {
FileInputStream in = new FileInputStream(file);
OutputStream out = response.getOutputStream();
byte[] b = new byte[1024 * 5];
int n;
while ((n = in.read(b)) != -1) {
out.write(b, 0, n);
}
out.flush();
in.close();
out.close();
}
}
}
工具类中配置了项目的路径,一个是临时模板,另一个是字体,需要放入相应的路径下,临时模板不用建,项目会自动生成,字体需要进行引入
配置相应的模板!!!重点
先使用world画出模板的表格,我这边使用的是office 2019,然后转化为HTML格式
转化的链接Word转HTML——免费在线Word转网页 (docpe.com)
将转化的html后缀修改为ftl格式,并且在插入值得地方用${值}表示
注意!!!
我这边遇到了一个font-family字体无法转化的bug,修改方法是将项目中的所有的font-family用空格替换掉
然后调用main方法进行测试
public static void main(String[] args) throws Exception {
Map<String, Object> paramMap = new HashMap<String, Object>();
paramMap.put("XM", "張三冯");
paramMap.put("AH", "(2015)****字第0***0号");
paramMap.put("CSKSRQ", "2016年10月31日00时00分");
paramMap.put("KHZH", "271**********07279975");
paramMap.put("FYMC", "****人民法院");
paramMap.put("JSRQ", "2017-06-14");
paramMap.put("KZZT", "1");
paramMap.put("LCZH", "987234234");
paramMap.put("DATE", "2017年03月24日09时39分");
paramMap.put("CKWH", "(2015)*****字第0**20-1**0号裁定书");
paramMap.put("SKSE", "100");
paramMap.put("CSJSRQ", "2016年10月31日 00时00分");
paramMap.put("KHWD", "images/stamp.jpg");
ContractDynamicParam param = new ContractDynamicParam(TEMPLATES_PATH, "pdfDemo.ftl", CONTRACT_PATH, "pdfDemo5.pdf", paramMap);
GeneratePdfUtil.GenerateContract(param);
System.out.println("====test生成PDF合同成功====");
}
至此就完成了,以后有空会补充一下具体细节
|