直接奔入正题,首先引入下方maven依赖复制到pom.xml中,如果不是maven项目,可到https://search.maven.org/ 直接去下载。
<dependency>
<groupId>org.xhtmlrenderer</groupId>
<artifactId>flying-saucer-pdf-itext5</artifactId>
<version>9.0.6</version>
</dependency>
<dependency>
<groupId>org.freemarker</groupId>
<artifactId>freemarker</artifactId>
<version>2.3.28</version>
</dependency>
下面代码撸起来
import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.OutputStream;
import java.io.StringWriter;
import org.xhtmlrenderer.pdf.ITextFontResolver;
import org.xhtmlrenderer.pdf.ITextRenderer;
import com.itextpdf.text.pdf.BaseFont;
import com.tintinloan.codelets.support.exception.BusinessException;
import freemarker.template.Configuration;
import freemarker.template.Template;
import freemarker.template.TemplateExceptionHandler;
import net.sf.json.JSONObject;
/***
*
* 作者:
*
* 创建时间:2019年7月29日 下午2:25:56
*
* 实现功能:ftl转html转PDF工具类
*/
public class Html2Pdf {
/***
* 通过模板转换为html
* @param modeName 模板名称
* @param params 参数
* @return html的字符串形式
* @throws Exception
*/
public String createHtmlStr(String modelName, JSONObject params) {
Configuration cfg = new Configuration(Configuration.VERSION_2_3_28);
try {
// 设置模板所在路径
cfg.setDirectoryForTemplateLoading(new File("D:\\ftl"));
// 设置默认编码
cfg.setDefaultEncoding("utf-8");
//若发生错误,HTML_DEBUG_HANDLER会生成错误信息到生成页面;RETHROW_HANDLER错误信息会输出到控制台
cfg.setTemplateExceptionHandler(TemplateExceptionHandler.RETHROW_HANDLER);
} catch (IOException e) {
e.printStackTrace();
}
StringWriter out = null;
try {
// 创建模版对象
Template template = cfg.getTemplate(modelName);
out = new StringWriter();
// 模版数据插入参数,通过输出流插入到HTML中
template.process(params, out);
} catch (Exception e) {
throw new BusinessException(e.getMessage());
} finally {
if (null != out) {
try {
out.flush();
out.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
return out.toString();
}
/***
* 把html字符串转换为PDF
* @param outputFile
* @param content
* @throws Exception
*/
public boolean htmlToPdf(String outputFile, String content) throws IOException,DocumentException {
File outFile = new File(outputFile);
if (!outFile.exists()) {
outFile.getParentFile().mkdirs();
}
/*
* response.setHeader("Content-disposition","attachment;filename=test.pdf");
* response.setContentType("application/pdf");
* OutputStream os = response.getOutputStream();
*/
OutputStream os = new FileOutputStream(outputFile);
ITextRenderer renderer = new ITextRenderer();
// 该参入是传入需要转为PDF的页面的网络路径,比如:http://xxx.xxx/xxx.html
// 或者可以返回modelAndview的controller
// renderer.setDocument(url);
// 该参入是传入需要转为PDF的HTML字符串
renderer.setDocumentFromString(content);
// 将宋体文件
String fontPath = "D\\ttc\\simsun.ttc";
// 设置中文字体
ITextFontResolver fontResolver = renderer.getFontResolver();
fontResolver.addFont(fontPath, BaseFont.IDENTITY_H, BaseFont.NOT_EMBEDDED);
renderer.layout();
renderer.createPDF(os);
renderer.finishPDF();
os.flush();
os.close();
return true;
}
}
上面两个方法中第一个是将ftl转换成HTML并返回HTML的string形式,第二个方法是将HTML转换为pdf文件并保存到指定的路径下。注释很详细,就不单独细说了。字体文件下载地址,下载后解压后放到D:/ttc文件夹下
链接:https://pan.baidu.com/s/1xxONpDF_zUAYZC0o4M477Q 提取码:nufc
下面开始定义一个ftl模板文件放到D:/ftl文件夹下,模板文件名称为:test.ftl
<html>
<head>
<title>测试ftl</title>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
<style type='text/css'>
<!-- 设置页面大小 -->
@page {
size: 297mm 210mm;
}
</style>
</head>
<!-- body中要设置文字的字体,与Java代码中引用的字体一致 -->
<body bgcolor='white'
style='font-family: SimSun; height: 100%;word-break: break-all;'
screen_capture_injected='true' ryt11773='1'>
<div class="" style="margin-top:5px">
<p
style="background-color: #ffffff;; line-height: 125%; margin: 0pt; text-align: center">
<span style="font-size:25px;font-weight: bold">${content}</span>
</p>
</div>
</body>
</html>
模板写好之后,开始调用测试能不能生成就可以了。
public static void main(String[] args) {
// PDF生成后存放目录
final String outputFile = "D://ftest.pdf";
Html2Pdf html2Pdf = new Html2Pdf();
// 创建jsonobject对象给ftl模板传参
JSONObject json = new JSONObject();
json.put("content","Hello World!");
try {
html2Pdf.htmlToPdf(outputFile, html2Pdf.createHtmlStr("test.ftl", json));
} catch (IOException | DocumentException e) {
e.printStackTrace();
}
}
运行后,就是这样的了。其他的api自行研究吧。
如果完成上面这一步,不要高兴的太早:
看下面这张图,明白了什么?
这就是我要特别提醒的:有时候,在HTML转PDF的时候页面转换错误,或者标签解析错误,那是因为仅支持css2.1样式,itext支持5.x。大家应该都懂得。所以如果页面需要转换为PDF,那么请放下你大神的姿态。
就这样了,如有更好的解决方案可共同探讨。