iText是java的一个类库,可以直接生成pdf文档,或者通过html模板生成pdf文档。使用html生成文档的方式比较方便前端同事开发页面(后端开发大部分审美确实是呵呵……),所以一般选用此种方式。
先列出此种方式容易遇到的几个问题:
- html标签需要严格闭合,不然会报错。如
</p>,<br></br>,<img></img>等。注意,不支持<img src = "" />
此类写法。 - 如果html中有引用图片,那么图片必须使用绝对路径,并且加上"file:///"前缀。
- 中文支持问题,由于itext默认不支持中文,所以需要手动指定中文字体。字体文件一般可以在window系统的C:\Windows\Fonts路径找到,如果使用liunx系统,可以将字体文件直接复制到liunx下使用。
如果html中有需要动态替换的内容,建议使用ftl文件代替html文件。话不多说,直接上代码。
ftl模板:
<html>
<head>
<title>ECO 模板</title>
</head>
<body style="margin:0; padding:0; font-family: STFANGSO.TTF;">
<div style="width:190mm; margin:0 auto; padding:0">
<div style="padding:30px;">
<div style="display:table; width:100%; margin:0 auto;">
<table border="0" cellpadding="0" cellspacing="0" width="100%" align="left" style="border-collapse: collapse; margin:10px 0">
<tbody>
<tr>
<td width="50%">
<table>
<tr>
<td valign="middle">
<img src="${sinnetCloudPic}" alt="logo" width="120" height="42" style="vertical-align: middle;" ></img>
<span style="color:rgba(255, 147, 16, 1); font-size:13px; font-weight: bold; padding-left: 10px">有限公司</span>
</td>
</tr>
<tr><td style="padding:20px 0"></td></tr>
<tr>
<td style="font-size:16px;font-weight: bold;padding:5px 0;line-height:32px;list-style: none;">客户名称:</td>
</tr>
<tr>
<td style="word-break: break-all;font-size:14px; font-weight: normal; line-height:28px;">${customerName}</td>
</tr>
<tr>
<td style="font-size:16px;font-weight: bold;padding:5px 0;line-height:32px;list-style: none;">公司地址:</td>
</tr>
<tr>
<td style="word-break: break-all;font-size:14px; font-weight: normal; line-height:28px;">${customerAddress}</td>
</tr>
</table>
</td>
<td width="50%">
<table width="100%">
<tr>
<td colspan="2" style="font-size:14px;line-height: 24px;">付款通知</td>
</tr>
<tr>
<td colspan="2" style="font-size:14px;line-height: 24px;">如果您遇到任何关于账户账单问题,请通过邮件联系我们。</td>
</tr>
<tr>
<td colspan="2" style="font-size:14px;line-height: 24px;">客服邮箱:</td>
</tr>
<tr>
<td colspan="2" style="padding:10px 0; font-size:14px; font-weight:bold; text-align:left; ">付款账单总览</td>
</tr>
<tr>
<td style="color:rgba(53, 53, 53, 1); font-size:14px; padding:10px 0; border-top:1px dashed rgba(255, 147, 16, 1);">账单号:</td>
<td style="color:rgba(53, 53, 53, 1); font-size:14px; text-align:right; padding:10px 0; border-top:1px dashed rgba(255, 147, 16, 1);">${orderBillCode}</td>
</tr>
<tr>
<td colspan="2" style="font-size:12px; color:rgba(204,204,204,1); padding:0px 0px 10px 0; margin:0">进行电子资金转账付款时,请务必引用上述账单号。</td>
</tr>
<tr>
<td style="color:rgba(53, 53, 53, 1); font-size:14px; padding:10px 0; border-top:1px dashed rgba(255, 147, 16, 1);">账单通知日期:</td>
<td style="color:rgba(53, 53, 53, 1); font-size:14px; padding:10px 0; border-top:1px dashed rgba(255, 147, 16, 1); text-align:right;">${billDate}</td>
</tr>
<tr>
<td style="color:rgba(53, 53, 53, 1); font-size:14px; padding:10px 0; border-top:1px dashed rgba(255, 147, 16, 1);">账单总金额:</td>
<td style="color:rgba(53, 53, 53, 1); font-size:14px; padding:10px 0; border-top:1px dashed rgba(255, 147, 16, 1); text-align:right;">${billMoney}</td>
</tr>
</table>
</td>
</tr>
</tbody>
</table>
</div>
</div>
</div>
</body>
</html>
pom.xml
<!-- 生成pfd-->
<dependency>
<groupId>com.itextpdf</groupId>
<artifactId>itext-asian</artifactId>
<version>5.2.0</version>
</dependency>
<dependency>
<groupId>com.itextpdf</groupId>
<artifactId>itextpdf</artifactId>
<version>5.5.12</version>
</dependency>
<dependency>
<groupId>com.itextpdf.tool</groupId>
<artifactId>xmlworker</artifactId>
<version>5.5.8</version>
</dependency>
<!-- ftl模板-->
<dependency>
<groupId>org.freemarker</groupId>
<artifactId>freemarker</artifactId>
<version>2.3.22</version>
</dependency>
Ftl工具类
package com.sinnet.eco.utils;
import freemarker.template.Configuration;
import freemarker.template.Template;
import freemarker.template.TemplateException;
import java.io.File;
import java.io.IOException;
import java.io.StringWriter;
import java.util.HashMap;
import java.util.Map;
public class GuoFtlUtil {
/**
* ftl文件替换数据并返回字符串
*
* @param ftlDir
* @param ftlName
* @param paramMap
* @return
* @throws IOException
* @throws TemplateException
*/
public static String ftlToString(String ftlDir, String ftlName, Map paramMap) throws IOException, TemplateException {
Configuration cfg = new Configuration(Configuration.getVersion());
cfg.setDefaultEncoding("UTF-8");
cfg.setNumberFormat("0.00");
cfg.setDirectoryForTemplateLoading(new File(ftlDir));
Template template = cfg.getTemplate(ftlName);
StringWriter writer = new StringWriter();
template.process(paramMap, writer);
writer.flush();
String htmlTemplate = writer.toString();
writer.close();
return htmlTemplate;
}
}
pdf工具类
package com.sinnet.eco.utils;
import com.itextpdf.text.*;
import com.itextpdf.text.pdf.BaseFont;
import com.itextpdf.text.pdf.PdfWriter;
import com.itextpdf.tool.xml.XMLWorkerFontProvider;
import com.itextpdf.tool.xml.XMLWorkerHelper;
import java.io.*;
import java.nio.charset.Charset;
/**
* 生成pdf工具类
*
* @author guoj
* @date 2019-08-22
*/
public class GuoPdfUtil {
/**
* html模板的String生成pdf
*
* @param htmlTemplate
* @param pdfPathName
* @throws IOException
* @throws DocumentException
*/
public static void htmlTemplateToPdf(String htmlTemplate, String pdfPathName) throws IOException, DocumentException {
File pdf = new File(pdfPathName);
if (!pdf.getParentFile().exists()) {
pdf.getParentFile().mkdirs();
}
if (pdf.exists()) {
pdf.delete();
}
Document document = new Document(PageSize.LETTER);
PdfWriter pdfWriter = PdfWriter.getInstance(document,
new FileOutputStream(pdfPathName));
XMLWorkerHelper worker = XMLWorkerHelper.getInstance();
document.open();
worker.parseXHtml(pdfWriter, document, new ByteArrayInputStream(htmlTemplate.getBytes("UTF-8")), Charset.forName("UTF-8"), new AsianFontProvider());
document.close();
}
/**
* 字体类
*/
public static class AsianFontProvider extends XMLWorkerFontProvider {
public AsianFontProvider() {
super(null, null);
}
// @Override
// public Font getFont(final String fontname, String encoding, float size, final int style) {
// String fntname = fontname;
// if (fntname == null) {
// /**
// * 使用的windows里的宋体,可将其文件放资源文件中引入
// */
// String os = System.getProperties().getProperty("os.name");
// if (os.startsWith("win") || os.startsWith("Win")) {
// fntname = "simsun";
// } else {
// fntname = "simsun";
// }
fntname = "宋体";
// }
// if (size == 0) {
// size = 4;
// }
// System.out.print("-----fntname:"+fntname);
// return super.getFont(fntname, encoding, size, style);
// }
@Override
public Font getFont(String fontname, String encoding, boolean embedded, float size, int style, BaseColor color) {
//字体文件路径
String name = "";
//华文仿宋
String fontNameDefault = "STFANGSO.TTF";
if (fontname != null) {
/**
* 可以在html中指定字体,如在body中指定:font-family: SimSun.ttc;
*/
fontNameDefault = fontname;
}
String os = System.getProperties().getProperty("os.name").toLowerCase();
if (os.startsWith("win")) {
name = "E:/test/pdf/billpdf/ftl/" + fontNameDefault + "";
} else {
name = "/data/eco/billpdf/ftl/" + fontNameDefault + "";
}
//如果是ttc,需要如下处理
if (name.toLowerCase().contains("ttc")) {
name += ",1";
}
Font font = null;
try {
font = new Font(BaseFont.createFont(name, BaseFont.IDENTITY_H, BaseFont.EMBEDDED));
font.setStyle(style);
font.setColor(color);
if (size > 0) {
font.setSize(size);
}
} catch (DocumentException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
return font;
}
}
}
运行结果截图: