需求
实现:电子合同,电子回单、电子对账单等
需求插件(依赖)
1.基本插件
itextpdf
功能很强大,差不多可以实现PDF所有的功能。(如果你想实现有特殊需求的,如表单、PDF模板、水印等等都可以),需要特别注意的是它不支持中文,因此需要给它指定字体。
2.辅助插件(itextpdf 扩展插件)
为什么要用辅助插件呢,因为只需要itextpdf 基本功能就可以了,辅助插件可以帮你更少的代码实现功能。
2-1、xmlworker 根据XML生成PDF。
2-2、freemarker 根据XML 进行标记 进行填充。
2-3、flying-saucer-pdf 与 flying-saucer-pdf-itext5 根据XML里的图片等资源加载出来并生成PDF(场景:水印、印章等)
POM 文件
<dependencies>
<!-- PDF操作插件-->
<dependency>
<groupId>com.itextpdf</groupId>
<artifactId>itextpdf</artifactId>
<version>5.5.11</version>
</dependency>
<!-- 利用HTML 生成PDF-->
<dependency>
<groupId>com.itextpdf.tool</groupId>
<artifactId>xmlworker</artifactId>
<version>5.5.11</version>
</dependency>
<!-- 利用HTML 标记生成PDF-->
<dependency>
<groupId>org.freemarker</groupId>
<artifactId>freemarker</artifactId>
<version>2.3.19</version>
</dependency>
<!-- 利用HTML 支持带图片生成PDF-->
<dependency>
<groupId>org.xhtmlrenderer</groupId>
<artifactId>flying-saucer-pdf</artifactId>
<version>9.1.5</version>
</dependency>
<dependency>
<groupId>org.xhtmlrenderer</groupId>
<artifactId>flying-saucer-pdf-itext5</artifactId>
<version>9.1.5</version>
</dependency>
</dependencies>
为了获取文件资源,先准备一个工具类
package util;
import java.io.File;
public class PathUtil {
public static String getCurrentPath() {
Class<?> caller = getCaller();
if (caller == null) {
caller = util.PathUtil.class;
}
return getCurrentPath(caller);
}
public static Class<?> getCaller() {
StackTraceElement[] stack = (new Throwable()).getStackTrace();
if (stack.length < 3) {
return util.PathUtil.class;
}
String className = stack[2].getClassName();
try {
return Class.forName(className);
} catch (ClassNotFoundException e) {
e.printStackTrace();
}
return null;
}
public static String getCurrentPath(Class<?> cls) {
String path = cls.getProtectionDomain().getCodeSource().getLocation().getPath();
path = path.replaceFirst("file:/", "");
path = path.replaceAll("!/", "");
if (path.lastIndexOf(File.separator) >= 0) {
path = path.substring(0, path.lastIndexOf(File.separator));
}
if ("/".equalsIgnoreCase(path.substring(0, 1))) {
String osName = System.getProperty("os.name").toLowerCase();
if (osName.contains("window")) {
path = path.substring(1);
}
}
return path;
}
}
一、itextpdf 生成PDF
import com.itextpdf.text.*;
import com.itextpdf.text.pdf.BaseFont;
import com.itextpdf.text.pdf.PdfWriter;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
public class JavaToPdf {
private static final String DEST = "target/Test.pdf";
public static void main(String[] args) throws FileNotFoundException, DocumentException {
Document document = new Document();
PdfWriter writer = PdfWriter.getInstance(document, new FileOutputStream(DEST));
document.open();
Font f1 = FontFactory.getFont(FONT, BaseFont.IDENTITY_H, BaseFont.NOT_EMBEDDED);
document.add(new Paragraph("Test Create PDF", f1));
document.close();
writer.close();
}
}
二、itextpdf 生成的PDF 支持中文
准备一个中文字体放到资源文件夹(resources)下
代码
import com.itextpdf.text.*;
import com.itextpdf.text.pdf.BaseFont;
import com.itextpdf.text.pdf.PdfWriter;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
public class JavaToPdfCN {
private static final String DEST = "target/Test.pdf";
private static final String FONT = "simhei.ttf";
public static void main(String[] args) throws FileNotFoundException, DocumentException {
Document document = new Document();
PdfWriter writer = PdfWriter.getInstance(document, new FileOutputStream(DEST));
document.open();
Font f1 = FontFactory.getFont(FONT, BaseFont.IDENTITY_H, BaseFont.NOT_EMBEDDED);
document.add(new Paragraph("Test Create PDF 支持中文", f1));
document.close();
writer.close();
}
}
三、通过HTML生成PDF
准备文件template.html 并放在资源目录下
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8"/>
<title>Title</title>
<style>
body{
font-family:SimHei;
}
.red{
color: red;
}
</style>
</head>
<body>
<div class="red">
这是通过HTML 生成的PDF
</div>
</body>
</html>
import com.itextpdf.text.Document;
import com.itextpdf.text.DocumentException;
import com.itextpdf.text.pdf.PdfWriter;
import com.itextpdf.tool.xml.XMLWorkerFontProvider;
import com.itextpdf.tool.xml.XMLWorkerHelper;
import util.PathUtil;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.nio.charset.Charset;
public class JavaToPdfHtml {
private static final String DEST = "target/HTMLtoPdf.pdf";
private static final String HTML = PathUtil.getCurrentPath()+"/template.html";
private static final String FONT = "simhei.ttf";
public static void main(String[] args) throws IOException, DocumentException {
// step 1
Document document = new Document();
// step 2
PdfWriter writer = PdfWriter.getInstance(document, new FileOutputStream(DEST));
// step 3
document.open();
// step 4
XMLWorkerFontProvider fontImp = new XMLWorkerFontProvider(XMLWorkerFontProvider.DONTLOOKFORFONTS);
fontImp.register(FONT);
XMLWorkerHelper.getInstance().parseXHtml(writer, document,
new FileInputStream(HTML), null, Charset.forName("UTF-8"), fontImp);
// step 5
document.close();
}
}
三、利用HTML作为生成PDF的模板 生成PDF
准备
在资源目录下创建HTML:template_freemarker.html
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8"/>
<title>Title</title>
<style>
body{
font-family:SimHei;
}
.blue{
color: blue;
}
.pos{
position:absolute;
left:100px;
top:150px
}
</style>
</head>
<body>
<div class="blue pos">
账户:${name}. 你的账款余额:${mm}
</div>
</body>
</html>
import com.itextpdf.text.Document;
import com.itextpdf.text.DocumentException;
import com.itextpdf.text.pdf.PdfWriter;
import com.itextpdf.tool.xml.XMLWorkerFontProvider;
import com.itextpdf.tool.xml.XMLWorkerHelper;
import freemarker.template.Configuration;
import java.io.*;
import java.nio.charset.Charset;
import java.util.HashMap;
import java.util.Map;
import freemarker.template.Template;
import util.PathUtil;
public class JavaToPdfHtmlFreeMarker {
private static final String DEST = "target/HTMLModelToPdf.pdf";
private static final String HTML = "template_freemarker.html";
private static final String FONT = "simhei.ttf";
private static Configuration freemarkerCfg = null;
static {
freemarkerCfg =new Configuration();
//freemarker的模板目录
try {
freemarkerCfg.setDirectoryForTemplateLoading(new File(PathUtil.getCurrentPath()));
} catch (IOException e) {
e.printStackTrace();
}
}
public static void createPdf(String content,String dest) throws IOException, DocumentException {
// step 1
Document document = new Document();
// step 2
PdfWriter writer = PdfWriter.getInstance(document, new FileOutputStream(dest));
// step 3
document.open();
// step 4
XMLWorkerFontProvider fontImp = new XMLWorkerFontProvider(XMLWorkerFontProvider.DONTLOOKFORFONTS);
fontImp.register(FONT);
XMLWorkerHelper.getInstance().parseXHtml(writer, document,
new ByteArrayInputStream(content.getBytes()), null, Charset.forName("UTF-8"), fontImp);
// step 5
document.close();
}
/**
* freemarker渲染html
*/
public static String freeMarkerRender(Map<String, Object> data, String htmlTmp) {
Writer out = new StringWriter();
try {
// 获取模板,并设置编码方式
Template template = freemarkerCfg.getTemplate(htmlTmp);
template.setEncoding("UTF-8");
// 合并数据模型与模板
template.process(data, out); //将合并后的数据和模板写入到流中,这里使用的字符流
out.flush();
return out.toString();
} catch (Exception e) {
e.printStackTrace();
} finally {
try {
out.close();
} catch (IOException ex) {
ex.printStackTrace();
}
}
return null;
}
public static void main(String[] args) throws IOException, DocumentException {
Map<String,Object> data = new HashMap();
data.put("name","张三");
data.put("mm","100");
String content = JavaToPdfHtmlFreeMarker.freeMarkerRender(data,HTML);
JavaToPdfHtmlFreeMarker.createPdf(content,DEST);
}
}
三、利用HTML作为生成PDF的模板 生成PDF (升级 支持HTML里的图片资源显示)
准备
代码
import com.itextpdf.text.DocumentException;
import com.itextpdf.text.pdf.BaseFont;
import flyingsaucer.JavaToPdfHtmlFreeMarker;
import util.PathUtil;
import freemarker.template.Configuration;
import freemarker.template.Template;
import org.xhtmlrenderer.pdf.ITextFontResolver;
import org.xhtmlrenderer.pdf.ITextRenderer;
import java.io.*;
import java.util.HashMap;
import java.util.Map;
public class JavaToPdfHtmlFreeMarkerForImage {
private static final String DEST = "target/HTMLModelToPdfForImage.pdf";
private static final String HTML = "template_freemarker_fs.html";
private static final String FONT = "simhei.ttf";
private static final String LOGO_PATH = "file://logo.png";
private static Configuration freemarkerCfg = null;
static {
freemarkerCfg =new Configuration();
//freemarker的模板目录
try {
freemarkerCfg.setDirectoryForTemplateLoading(new File(PathUtil.getCurrentPath()));
} catch (IOException e) {
e.printStackTrace();
}
}
/**
* freemarker渲染html
*/
public static String freeMarkerRender(Map<String, Object> data, String htmlTmp) {
Writer out = new StringWriter();
try {
// 获取模板,并设置编码方式
Template template = freemarkerCfg.getTemplate(htmlTmp);
template.setEncoding("UTF-8");
// 合并数据模型与模板
template.process(data, out); //将合并后的数据和模板写入到流中,这里使用的字符流
out.flush();
return out.toString();
} catch (Exception e) {
e.printStackTrace();
} finally {
try {
out.close();
} catch (IOException ex) {
ex.printStackTrace();
}
}
return null;
}
public static void createPdf(String content,String dest) throws IOException, DocumentException, com.lowagie.text.DocumentException {
ITextRenderer render = new ITextRenderer();
ITextFontResolver fontResolver = render.getFontResolver();
fontResolver.addFont(FONT, BaseFont.IDENTITY_H, BaseFont.NOT_EMBEDDED);
// 解析html生成pdf
render.setDocumentFromString(content);
//解决图片相对路径的问题
render.getSharedContext().setBaseURL(LOGO_PATH);
render.layout();
render.createPDF(new FileOutputStream(dest));
}
public static void main(String[] args) throws DocumentException, com.lowagie.text.DocumentException, IOException {
Map<String,Object> data = new HashMap();
data.put("name","显示图片测试");
String content = JavaToPdfHtmlFreeMarker.freeMarkerRender(data,HTML);
JavaToPdfHtmlFreeMarker.createPdf(content,DEST);
}
参考实现