前言
目前好多报表及样式打印都有需要pdf格式,但是人们又习惯了html画页面,当然这是由于本身PDF去画页面样式是有一定难度的,若是你特别精通PDF,当我没说。那么有没有什么工具可以直接将html页面直接转换成pdf呢,当然是有的,目前我已知的有两种,jasper 和iitextpdf,该文,仅介绍itextpdf转pdf遇到的一些坑。
正文
### 一
jar
<dependency>
<groupId>com.itextpdf</groupId>
<artifactId>html2pdf</artifactId>
<version>5.0.2</version>
</dependency>
转换代码
package com.zf;
import com.itextpdf.html2pdf.HtmlConverter;
import java.io.File;
import java.io.IOException;
public class Test {
public static void main(String[] args) throws Exception {
String baseDir = "C:\\Users\\zhangfeng\\Desktop\\testt\\";
String htmlFile = baseDir+"test.html";
String pdfFile = baseDir+"test.pdf";
HtmlConverter.convertToPdf(new File(htmlFile),new File(pdfFile));
}
}
html页面
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Title</title>
</head>
<body>
<div>dhakdhaksda</div>
<div>你好我好大家好</div>
</body>
</html>
pdf页面
这时,大家会发现中文丢失,这是itextpdf 工具html转pdf 的第一个通用问题。这个问题很好解决,引入字体设置就可以了。上代码
###二
jar 包
<dependency>
<groupId>com.itextpdf</groupId>
<artifactId>html2pdf</artifactId>
<version>5.0.2</version>
</dependency>
<dependency>
<groupId>com.itextpdf</groupId>
<artifactId>itext-asian</artifactId>
<version>5.2.0</version>
</dependency>
添加字体(记得添加ttf的,ttc的需要设置什么,不然不会识别)
public static void main(String[] args) throws Exception {
String baseDir = "C:\\Users\\zhangfeng\\Desktop\\testt\\";
String htmlFile = baseDir+"test.html";
String pdfFile = baseDir+"test1.pdf";
String fontPath = "C:\\Windows\\Fonts\\simkai.ttf";
ConverterProperties converterProperties = new ConverterProperties();
FontProvider fontProvider = new FontProvider();
fontProvider.addFont(fontPath);
converterProperties.setFontProvider(fontProvider);
HtmlConverter.convertToPdf(new File(htmlFile),new File(pdfFile),converterProperties);
}
结果
简单的模板样式都可以这样转换,但是如果有复杂的html页面,这样转换你会发现,好多html标签及css样式不生效。
故这里展示第二种itext htnl转pdf 的方法
jar
<dependency>
<groupId>com.itextpdf</groupId>
<artifactId>itextpdf</artifactId>
<version>5.5.13.3</version>
</dependency>
<dependency>
<groupId>com.itextpdf.tool</groupId>
<artifactId>xmlworker</artifactId>
<version>5.5.13.3</version>
</dependency>
public static void main(String[] args) throws Exception {
String baseDir = "C:\\Users\\zhangfeng\\Desktop\\testt\\";
String htmlFile = baseDir+"test.html";
String pdfFile = baseDir+"test3.pdf";
String fontPath = "C:\\Windows\\Fonts\\simkai.ttf";
Document document = new Document();//这里可以设置纸张大小
PdfWriter instance1 = PdfWriter.getInstance(document, new FileOutputStream(new File(pdfFile)));
document.open();
//当然这里也要设置字体,不然中文无法显示
FontProvider fontProvider = new FontProvider(){
@Override
public boolean isRegistered(String s) {
return false;
}
private BaseFont createFont(){
try{
return BaseFont.createFont(fontPath,BaseFont.IDENTITY_H,BaseFont.EMBEDDED);
}catch(Exception ex){
ex.printStackTrace();
}
return null;
}
@Override
public Font getFont(String s, String s1, boolean b, float v, int i, BaseColor baseColor) {
return new Font(createFont(),v,i,baseColor);
}
};
XMLWorkerHelper instance = XMLWorkerHelper.getInstance();
instance.parseXHtml(instance1,document,new FileInputStream(new File(htmlFile)), StandardCharsets.UTF_8,fontProvider);
document.close();
}
注意点:
1注意标签一定要闭合,不然
Exception in thread "main" com.itextpdf.tool.xml.exceptions.RuntimeWorkerException: Invalid nested tag head found, expected closing tag meta.
结果:
2注意table 标签中一定要有tr td 不然
Exception in thread "main" java.lang.IllegalArgumentException: The number of columns in PdfPTable constructor must be greater than zero.
3 如果像设置背景图片,在html 设置是不在pdf转换过程中生效的,可以换种方式。
public static void main(String[] args) throws Exception {
String baseDir = "C:\\Users\\zhangfeng\\Desktop\\testt\\";
String htmlFile = baseDir+"test.html";
String pdfFile = baseDir+"test4.pdf";
String fontPath = "C:\\Windows\\Fonts\\simkai.ttf";
String imagePath = baseDir+"aa.png";
Document document = new Document();//这里可以设置纸张大小
PdfWriter instance1 = PdfWriter.getInstance(document, new FileOutputStream(new File(pdfFile)));
document.open();
Image image = Image.getInstance(imagePath);
image.setAbsolutePosition(0,0);
image.scaleAbsolute(595,842);
document.add(image);
//当然这里也要设置字体,不然中文无法显示
FontProvider fontProvider = new FontProvider(){
@Override
public boolean isRegistered(String s) {
return false;
}
private BaseFont createFont(){
try{
return BaseFont.createFont(fontPath,BaseFont.IDENTITY_H,BaseFont.EMBEDDED);
}catch(Exception ex){
ex.printStackTrace();
}
return null;
}
@Override
public Font getFont(String s, String s1, boolean b, float v, int i, BaseColor baseColor) {
return new Font(createFont(),v,i,baseColor);
}
};
XMLWorkerHelper instance = XMLWorkerHelper.getInstance();
instance.parseXHtml(instance1,document,new FileInputStream(new File(htmlFile)), StandardCharsets.UTF_8,fontProvider);
document.close();
}
记得html页面body 透明度设置为0 即opacity: 0;
当然这样设置背景还有一个弊端,就是pdf有多页,这个只显示一页。若要设置多页,需在监听事件中设置背景图片,代码如下:
package com.zf;
import com.itextpdf.text.*;
import com.itextpdf.text.pdf.BaseFont;
import com.itextpdf.text.pdf.PdfIndirectReference;
import com.itextpdf.text.pdf.PdfPageEventHelper;
import com.itextpdf.text.pdf.PdfWriter;
import com.itextpdf.tool.xml.XMLWorkerHelper;
import java.io.*;
import java.nio.charset.StandardCharsets;
public class Test {
public static void main(String[] args) throws Exception {
String baseDir = "C:\\Users\\zhangfeng\\Desktop\\testt\\";
String htmlFile = baseDir+"test.html";
String pdfFile = baseDir+"test4.pdf";
String fontPath = "C:\\Windows\\Fonts\\simkai.ttf";
String imagePath = baseDir+"aa.png";
Document document = new Document();//这里可以设置纸张大小
PdfWriter instance1 = PdfWriter.getInstance(document, new FileOutputStream(new File(pdfFile)));
document.open();
instance1.setPageEvent(new BackAdd());
//当然这里也要设置字体,不然中文无法显示
FontProvider fontProvider = new FontProvider(){
@Override
public boolean isRegistered(String s) {
return false;
}
private BaseFont createFont(){
try{
return BaseFont.createFont(fontPath,BaseFont.IDENTITY_H,BaseFont.EMBEDDED);
}catch(Exception ex){
ex.printStackTrace();
}
return null;
}
@Override
public Font getFont(String s, String s1, boolean b, float v, int i, BaseColor baseColor) {
return new Font(createFont(),v,i,baseColor);
}
};
XMLWorkerHelper instance = XMLWorkerHelper.getInstance();
instance.parseXHtml(instance1,document,new FileInputStream(new File(htmlFile)), StandardCharsets.UTF_8,fontProvider);
document.close();
}
}
class BackAdd extends PdfPageEventHelper{
public void onCloseDocument(PdfWriter writer, Document document) {
String baseDir = "C:\\Users\\zhangfeng\\Desktop\\testt\\";
String imagePath = baseDir+"aa.png";
Image image = null;
try {
image = Image.getInstance(imagePath);
image.setAbsolutePosition(0,0);
image.scaleAbsolute(595,842);
document.add(image);
} catch (BadElementException e) {
e.printStackTrace();
} catch (Exception e) {
e.printStackTrace();
}
}
}