本文由 简悦 SimpRead 转码, 原文地址 blog.csdn.net
1、 iText 介绍
iText 是用于生成 PDF 文档的一个 java 类库。通过 iText 不仅可以生成 PDF 或 rtf 的文档,而且可以将 XML、Html 文件转化为 PDF 文件。官网地址 http://itextpdf.com。
2、Spring boot 项目 iText 依赖
itextpdf.jar 是 iText 的核心库,提供了用于创建和操作 PDF 文档的基本功能,itext-asian.jar 是 itext 库中关于亚洲编码的类库,特别适用于处理中文字符,处理中文乱码。
<dependency>
<groupId>com.itextpdf</groupId>
<artifactId>itextpdf</artifactId>
<version>5.5.11</version>
</dependency>
<dependency>
<groupId>com.itextpdf</groupId>
<artifactId>itext-asian</artifactId>
<version>5.2.0</version>
</dependency>
3、实现方式
3.1 一般性(不复杂 PDF)处理
下面写了 junit 测试。
@Test
public void testPdf() {
try {
Document document = new Document();
PdfWriter writer PdfWriter.getInstance(document, new
FileOutputStream("d:/hello.pdf"));
document.open();
Element element = new Paragraph("helloword!");
document.add(element);
document.close();
} catch (DocumentException e) {
e.printStackTrace();
} catch (FileNotFoundException e) {
e.printStackTrace();
}finally {
doc.close();
writer.close();
}
}
如果要实现 Http 导出 PDF,代码如下
public void exportPdf(HttpServletResponse response) {
try {
Document document = new Document();
OutputStream out = response.getOutputStream();
ByteArrayOutputStream baos = new ByteArrayOutputStream();
PdfWriter writer PdfWriter.getInstance(document, new
baos);
document.open();
Element element = new Paragraph("helloword!");
document.add(element);
response.setContentType("application/pdf");
response.setHeader("Content-Disposition", "inline; file);
out.write(baos.toByteArray());
out.flush();
} catch (DocumentException e) {
e.printStackTrace();
} catch (FileNotFoundException e) {
e.printStackTrace();
}finally {
// 关闭流....
}
}
3.2 格式、样式复杂的 Pdf 处理
在处理格式和样式复杂的 pdf 时候,为排版的美观,需要拼接 html,再将 html 转成 pdf。我这里手动拼接 html,此时需要依赖 xmlworker 包,
<dependency>
<groupId>com.itextpdf.tool</groupId>
<artifactId>xmlworker</artifactId>
<version>5.5.13.2</version>
</dependency>
形成 html 方法定义,这里可以定义很多格式和样式,实现自由扩展。
private String createHtml(String base64,Map<String,Object> headMap,List data){
StringBuffer stringBuffer = new StringBuffer();
createHtmlPic(stringBuffer,base64);
// 传入headMap,是为了支持动态表头
createHtmlTableHead(stringBuffer,headMap);
createHtmlTableData(stringBuffer,data);
return stringBuffer.toString() ;
}
生成 pdf 方法
public void exportPdfData(String base64,Map<String,Object> headMap,List data,String dir) {
File outFile = new File(dir);
// 创建动态html
String strHtml = createHtml( base64, headMap, data);
//html 转pdf
BaseFont bfChinese = null;
try {
bfChinese = BaseFont.createFont("STSongStd-Light", "UniGB-UCS2-H", BaseFont.NOT_EMBEDDED);
} catch (DocumentException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}catch (Exception e){
e.printStackTrace();
e.printStackTrace();
}
Font font = new Font(bfChinese, 9, Font.NORMAL);
font1.setColor(new BaseColor(255,255,255));
Document doc = new Document(new RectangleReadOnly(842F, 595F));
PdfWriter writer =null;
try {
writer = PdfWriter.getInstance(doc,new FileOutputStream(dir));
} catch (DocumentException e) {
e.printStackTrace();
} catch (FileNotFoundException e) {
e.printStackTrace();
}
//设置页面边距
doc.setMargins(20, 15, 20, 55);
if (writer != null){
writer.setPageEvent(new PageMarker());
}
doc.open();
try {
XMLWorkerHelper.getInstance().parseXHtml(writer, doc, new ByteArrayInputStream(strHtml.getBytes("UTF-8")), Charset.forName("UTF-8"),new FontProvider() {
@Override
public boolean isRegistered(String arg0) {
return false;
}
@Override
public Font getFont(String fontFamily, String charset, boolean arg2, float size, int style, BaseColor color) {
if("STSongStd-Light1".equals(fontFamily)){
return font1 ;
}else {
return font1 ;
}
}
});
} catch (IOException e) {
e.printStackTrace();
}finally {
doc.close();
writer.close();
}
}
入要 http 生成并且导出 pdf,请参照 3.1,本例子是我手动代码拼接 html。
3.3、使用 iText-Html-Freemarker 实现 pdf
其实 3.3 和 3.2 原理是一样的(都是将 html 转 pdf),只是 3.3 加入模板引擎支持,可以使用 FreeMarker。需要加入如下依赖。
<dependency>
<groupId>org.freemarker</groupId>
<artifactId>freemarker</artifactId>
<version>2.3.19</version>
</dependency>
添加模板 freemarker.html
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8"/>
<title>freemarker渲染HTML演示</title>
</head>
<body>
<div>${studentName}</div>
<div>${age}</div>
</body>
</html>
读取模板转出动态 html
Configuration freemarkerConfig = new Configuration();
//设置freemarker模板目录
freemarkerConfig.setDirectoryForTemplateLoading(new File("/export/pdf/"));
//获取指定的模板文件
Template template = freemarkerConfig.getTemplate("freemarker.html");
//设置编码方式
template.setEncoding("UTF-8");
//合并数据模型与模板,将合并后的数据和模板写入到流中,这里使用的字符流
Writer out = new StringWriter();
template.process(data, out);
out.flush();
String content = out.toString();
生产 pdf
public void exportPdfData(String strHtml String dir) {
File outFile = new File(dir);
BaseFont bfChinese = null;
try {
bfChinese = BaseFont.createFont("STSongStd-Light", "UniGB-UCS2-H", BaseFont.NOT_EMBEDDED);
} catch (DocumentException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}catch (Exception e){
e.printStackTrace();
e.printStackTrace();
}
Font font = new Font(bfChinese, 9, Font.NORMAL);
font1.setColor(new BaseColor(255,255,255));
Document doc = new Document(new RectangleReadOnly(842F, 595F));
PdfWriter writer =null;
try {
writer = PdfWriter.getInstance(doc,new FileOutputStream(dir));
} catch (DocumentException e) {
e.printStackTrace();
} catch (FileNotFoundException e) {
e.printStackTrace();
}
//设置页面边距
doc.setMargins(20, 15, 20, 55);
if (writer != null){
writer.setPageEvent(new PageMarker());
}
doc.open();
try {
XMLWorkerHelper.getInstance().parseXHtml(writer, doc, new ByteArrayInputStream(strHtml.getBytes("UTF-8")), Charset.forName("UTF-8"),new FontProvider() {
@Override
public boolean isRegistered(String arg0) {
return false;
}
@Override
public Font getFont(String fontFamily, String charset, boolean arg2, float size, int style, BaseColor color) {
if("STSongStd-Light1".equals(fontFamily)){
return font1 ;
}else {
return font1 ;
}
}
});
} catch (IOException e) {
e.printStackTrace();
}finally {
doc.close();
writer.close();
}
}
4 、注意
如果已经导入 itext-asian 依赖之后,还是出现中文乱码。可能是你使用的字体在你部署的服务上不存在。一般在 windows 机器找到对应的字体, 复制到对应目录,如果部署在 linux 要复制 / usr/share/fonts 目录。 一般要修改此目录的权限,并且执行 sudo fc-cache -fv 命令,是字体生效。