使用flying saucer生成PDF文件之前,先要使用freemarker生成html文件,然後將html文件轉成pdf。生成html文件的東東網上一搜一大堆,大家找找就成。
當然“使用flying saucer將html文件轉成PDF“的東東網上也是一搜一大堆,所以我這篇主要不是講怎麼生成,而是記載一路走來碰到的各種奇葩問題。
還是上一下轉成pdf文件的方法吧,可能以後有用:
Java代碼
/**
* 該方法用來將指定的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:在這個過程中有碰到其他問題的可以給我留言,我弄個總得,以後別人碰到相同問題就不用再走冤枉路了,多謝多謝!