使用flying saucer生成PDF文件之前,先要使用freemarker生成html文件,然后将html文件转成pdf。生成html文件的东东网上一搜一大堆,大家找找就成。
当然“使用flying saucer将html文件转成PDF“的东东网上也是一搜一大堆,所以我这篇主要不是讲怎么生成,而是记载一路走来碰到的各种奇葩问题。
还是上一下转成pdf文件的方法吧,可能以后有用:
/**
* 该方法用来将指定的word文件转换成pdf文件(使用flying saucer技术)
* @param pdfPath:生成后的pdf所在目录,包括目录+pdf名称+.+pdf
* @param htmlFilePath:需要进行转换的html文件所在目录,包括目录+html名称+.+html
* */
public boolean createPDFByHtml(String pdfPath,String htmlFilePath){
boolean result = false;
//1、判断给定的文件是否是html文件:是htm格式结尾,或者以html格式结尾
if(htmlFilePath.toUpperCase().endsWith(".HTM") ||
htmlFilePath.toUpperCase().endsWith(".HTML")){//两种格式都是扫描文件格式
try {
OutputStream os = new FileOutputStream(pdfPath);
ITextRenderer renderer = new ITextRenderer();
renderer.setDocument(new File(htmlFilePath));
// 解决中文支持问题
ITextFontResolver fontResolver = renderer.getFontResolver();
fontResolver.addFont("C:/Windows/Fonts/simsun.ttc", BaseFont.IDENTITY_H, BaseFont.NOT_EMBEDDED);
fontResolver.addFont("C:/Windows/Fonts/simhei.ttf", BaseFont.IDENTITY_H, BaseFont.NOT_EMBEDDED);
fontResolver.addFont("C:/Windows/Fonts/simkai.ttf", BaseFont.IDENTITY_H, BaseFont.NOT_EMBEDDED);
renderer.layout();
renderer.createPDF(os);
os.close();
result = true;
} catch (Exception e) {
result = false;
e.printStackTrace();
}
}else{
result = false;
}
return result ;
}
再说一下碰到的问题:
1、现象:不出现任何问题,pdf文件也不生成。使用debug跟踪,跟踪到ITextRenderer renderer = new ITextRenderer();时就进入到乱起八糟的东西里边去了,F8直接结束debug依旧不报错也不生成文件。
解决办法:将catch中的Exception改成Throwable,再一执行,开始报错了。
报错:org.xhtmlrenderer.util.XRRuntimeException: Can't load the XML resource (using TRaX transformer). java.io.IOException: Stream closed。
解决:通过将Exception改成Throwable才出现错误应该就能猜到,是jar包出问题了。将系统中的iText的jar包改成iText-2.0.8.jar,据网上说flying saucer已经停止更新,可能在开发这个功能时用的是2.0.8的版本,而iText一直在更新且后面的版本不支持2.0.8中的这个功能。
2、报错:java.lang.NoSuchMethodError: com.lowagie.text.pdf.BaseFont.getCharBBox(C)[I
解决:解决方法同1,替换jar包,只能换成2.0.8的,因为其他版本的都没有这个方法。
3、报错:org.xhtmlrenderer.util.XRRuntimeException: Can't load the XML resource (using TRaX transformer). org.xml.sax.SAXParseException: The entity "nbsp" was referenced, but not declared.
解决:这个是我做测试的时候报的错,当时测试时html文件很简单,只有基本标签,如<html><head><body>等。解决办法办是为html添加声明,即:
将<html>替换成
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
替换成别的版本的声明也行,我这个是因为css要求这样的声明,否则样式会出现问题。
4、报错:org.xhtmlrenderer.util.XRRuntimeException: Can't load the XML resource (using TRaX transformer). org.xml.sax.SAXParseException: The element type "meta" must be terminated by the matching end-tag "</meta>".
解决:说实话,这个问题我并没有碰到,因为我所有的标签都是结束了的,只是有些是使用简写,如<input />而不是<input></input>。之所以粘出来这个错误,因为我无法重现那个错误而他们两个报错的原因是一致的,都是因为标签没有结束。这个错误报的比较具体,有具体说到哪个标签,我测试时报的错比较迷糊,差不多就是说xml格式有问题,我查了下没发现问题,后来把所有的简写改成一对一对的标签才没有报错。由此可见,flying saucer对xml格式要求很严格。
5、现象:生成的pdf只显示数字和字母,不显示中文。
解决:网上大部分的解决办法都是说添加ITextFontResolver fontResolver = renderer.getFontResolver();fontResolver.addFont("C:/Windows/Fonts/SIMSUN.TTC", BaseFont.IDENTITY_H, BaseFont.NOT_EMBEDDED);只有真正试过的人才知道,只加了这一句根本就没用,即便是本地确实有这个文件或者换成别的所谓”宋体“的文件还是没有用,还有一个关键点:body{font-family: SimSun;}
所以总结起来三个点:
a、在生成pdf的方法中添加代码:ITextFontResolver fontResolver = renderer.getFontResolver();fontResolver.addFont("C:/Windows/Fonts/SIMSUN.TTC", BaseFont.IDENTITY_H, BaseFont.NOT_EMBEDDED);
b、确保C:/Windows/Fonts/SIMSUN.TTC这个文件确实存在(服务器上存在就成),若不存在从别的地方拷一个过来。
c、在模板文件页面添加样式:body{font-family: SimSun;}(SimSun只能是这样子,不能改,改成别的就不认了)
存在的问题:中文的问题是解决了,但是html中字体样式会丢失,如html文件中原本有加粗的字,转成pdf之后不再有加粗的字。
6、现象:生成的pdf左侧有边框,右侧没有边框
解决:我这里用的是table布局,table有定义宽度,每个td都有定义宽度,先将td的宽度调小,然后将table的宽度调小,可能要调小好几次然后才能出右侧边框。
最后祝大家好运
PS:在这个过程中有碰到其他问题的可以给我留言,我弄个总得,以后别人碰到相同问题就不用再走冤枉路了,多谢多谢!