`

使用flying saucer将html文件转成PDF

    博客分类:
  • Java
阅读更多

使用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:在这个过程中有碰到其他问题的可以给我留言,我弄个总得,以后别人碰到相同问题就不用再走冤枉路了,多谢多谢!

分享到:
评论

相关推荐

Global site tag (gtag.js) - Google Analytics