步骤一:写ftl格式的html
demo.ftl
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8"/>
<meta name="viewport" content="width=device-width, initial-scale=1.0"/>
<meta http-equiv="X-UA-Compatible" content="ie=edge"/>
<title>正式收据</title>
<style>
@page {
size: 297mm 120mm;
}
* {
padding: 0;
margin: 0;
}
ul,
li {
list-style: none;
}
body {
font-family: "FangSong", "STFangsong", "SimSun", "SimHei", "Helvetica", "Arial", "sans-serif";
font-size: 16px;
color: black;
background-color: transparent;
-webkit-font-smoothing: antialiased;
line-height: 1.42857143;
}
.receipt_box {
background: #FFFFFF;
border: 1px solid rgba(0, 0, 0, 0.13);
border-radius: 4px;
margin: 20px;
overflow: hidden;
}
.header {
width: 100%;
position: relative;
height: 100px;
overflow: hidden;
}
.logo {
position: absolute;
top: 14px;
left: 5px;
height: 39px;
width: 39px;
}
.date_box {
position: absolute;
top: 16px;
right: 0;
font-size: 12px;
color: #3D424D;
letter-spacing: 0;
line-height: 17px
}
.title_box {
padding: 0 0;
text-align: center;
}
.title_box .title {
font-size: 24px;
font-weight: bold;
color: #3D424D;
line-height: 32px;
margin: 9px 0 0 0;
}
</style>
</head>
<body>
<div class="receipt_box">
<div class="header">
<div class="title_box">
<p class="title">正式收据</p>
<span>OFFICIAL RECEIPT</span>
</div>
<img class="logo"
src="https://xxx.com"
alt=""/>
<div class="date_box">
<p style="word-break:break-all">No: ${receiptNo!}</p>
<p>Date: ${payTimeStr!}</p>
</div>
</div>
</div>
</body>
</html>
步骤二:使用freemarker将参数写入html里
Pom.xml
//Main.class
Map<?, ?> dataMap = new BeanMap(receipt);
String dataHtml = FreemarkerUtils.loadFtlHtml("/templates", "demo.ftl", dataMap);
FreemarkerUtils.class
Java
public class FreemarkerUtils {
private FreemarkerUtils() {
}
/**
* 使用传入的Map对象,渲染指定的freemarker模板
*
* @param pathName 根目录
* @param fileName 文件名
* @param globalMap 数据绑定
* @return html字符串
*/
public static String loadFtlHtml(String pathName, String fileName, Map globalMap) {
if (StringUtils.isEmpty(pathName) || StringUtils.isEmpty(fileName) || globalMap == null) {
throw new IllegalArgumentException("使用数据渲染模板时文件路径异常");
}
Configuration cfg = new Configuration(Configuration.VERSION_2_3_28);
try (StringWriter stringWriter = new StringWriter()) {
cfg.setClassForTemplateLoading(FreemarkerUtils.class, pathName);
cfg.setDefaultEncoding("UTF-8");
cfg.setTemplateExceptionHandler(TemplateExceptionHandler.RETHROW_HANDLER);
cfg.setClassicCompatible(true);
Template temp = cfg.getTemplate(fileName);
temp.process(globalMap, stringWriter);
return stringWriter.toString();
} catch (IOException | TemplateException e) {
log.error("使用数据渲染模板时异常", e);
throw new BaobabRuntimeException("使用数据渲染模板异常", e);
}
}
}
步骤三:使用Itext将html转成pdf
代码块
//Main.class
try (ByteArrayOutputStream byteArrayOutputStream = new ByteArrayOutputStream()) {
PdfFileUtils.html2pdf(byteArrayOutputStream, dataHtml);
return byteArrayOutputStream.toByteArray();
} catch (IOException e) {
throw new BaobabRuntimeException("生成pdf文件失败" + e);
}
//Html的String转Pdf工具类
public class PdfFileUtils {
/**
* 将HTML转成PD格式的文件。html文件的格式比较严格 图片问题,图片实际上需要用url链接而非本地,本地可能存在解析不了的问题。
*
* @param out
* @throws Exception
*/
public static void html2pdf(OutputStream out, String html) {
ITextRenderer renderer = new ITextRenderer();
try {
// 解决中文支持
ITextFontResolver fontResolver = renderer.getFontResolver();
fontResolver.addFont("/font/simsun.ttc", BaseFont.IDENTITY_H, BaseFont.NOT_EMBEDDED);
fontResolver.addFont("/font/simhei.ttf", BaseFont.IDENTITY_H, BaseFont.NOT_EMBEDDED);
renderer.setDocumentFromString(html);
renderer.layout();
renderer.createPDF(out);
log.info("create pdf done!!");
} catch (Exception e) {
throw new BaobabRuntimeException("生成 pdf 文件异常", e);
}
}
}
中文问题:
如果导出pdf需要中文,则需要使用ITextFontResolver将中文字体导入进去,如代码中的 fontResolver.addFont("/font/simsun.ttc", BaseFont.IDENTITY_H, BaseFont.NOT_EMBEDDED);
并且在html中设置字体: 而必须是SimSun 而不是sinsum
其他字体如fangsong之类的似乎导入失败了,不知道为什么识别不了
图片问题:
建议直接在html中引入http链接形式的图片,如: src=“https://s3plus.sankuai.com/v1/xxx”
尝试过本地图片的方式,当时需要设置其目录才可以正确识别,而不同系统的目录不一样,在本地运行可以成功但放到linux里却识别不了,比较麻烦,故不推荐
本地图片需要设置图片路径:
Java
renderer.getSharedContext().setBaseURL(“file:” + System.getProperty(“user.dir”) + “/xxx/src/main/resources/templates/”);