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; filename=chat_export.pdf");
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 命令,是字体生效。