Read Sean

          Read me, read Sean.
          posts - 508, comments - 655, trackbacks - 9, articles - 4

          iText vs FOP - Java動態生成PDF的兩個選擇

          Posted on 2008-10-05 23:28 laogao 閱讀(13769) 評論(11)  編輯  收藏 所屬分類: On Java

          由于工作需要,今天簡單的看了一下Java生成PDF的相關資料。綜合看下來,除了使用報表平臺和OOo的附帶工具,目前使用較為普遍的有兩個途徑:iText和Apache的FOP。從實際出發,我們分別看看兩者處理帶有中文的PDF的具體用法吧。

          [iText] (link)

          iText我想大概不少人都有所耳聞,JasperReports默認的PDF支持就來自這個軟件包,它處理速度快,支持很多PDF"高級"特性,如:Annotations、AcroForms、數字簽名、加密等,支持對已有PDF的處理,通過iTextAsian.jar和iTextAsianCmaps.jar,它對中文的支持也不錯。缺點是較為依賴Java代碼,需要學習不少的專有API,當輸入/輸出格式有變化時,需要修改代碼(除非手工寫一些wrapper),不夠靈活。目前的版本是2.1.3。具體代碼:

          Formatter.java
          ?1?import?java.io.FileOutputStream;
          ?2?
          ?3?import?com.lowagie.text.Document;
          ?4?import?com.lowagie.text.Font;
          ?5?import?com.lowagie.text.PageSize;
          ?6?import?com.lowagie.text.Paragraph;
          ?7?import?com.lowagie.text.pdf.BaseFont;
          ?8?import?com.lowagie.text.pdf.PdfWriter;
          ?9?
          10?public?class?Formatter?{
          11?
          12?????public?static?void?main(String[]?args)?throws?Exception?{
          13?????????Document?document?=?new?Document(PageSize.A4);
          14?????????try?{
          15?????????????System.out.print("Generating?PDF");
          16?????????????PdfWriter.getInstance(document,?new?FileOutputStream("test.pdf"));
          17?????????????document.open();
          18?????????????//iText自帶的中文字體
          19?????????????BaseFont?bf1?=?BaseFont.createFont("STSong-Light",?"UniGB-UCS2-H",?BaseFont.NOT_EMBEDDED);
          20?????????????//自定義字體
          21?????????????BaseFont?bf2?=?BaseFont.createFont("wqy-zenhei.ttf",?BaseFont.IDENTITY_H,?BaseFont.NOT_EMBEDDED);
          22?????????????Font?font?=?new?Font(bf2,?12,?Font.NORMAL);
          23?????????????Paragraph?p?=?new?Paragraph("測試abc中文123",?font);
          24?????????????document.add(p);
          25?????????????System.out.println("Done.");
          26?????????}?finally?{
          27?????????????document.close();
          28?????????}
          29?????}
          30?
          31?}

          效果:
          itext.png

          中文支持有默認的STSong-Light等字體,但為了優化輸出效果,這里使用了文泉驛正黑字體。如果不指定中文字體,默認情況下中文字符不會顯示。

          [FOP] (link)

          FOP出自Apache,在各大Java網站、論壇出現相對較低,我也是從DocBook這條線摸進來的,DocBook主要提供了一個現成的、符合一般技術書籍要求的數據結構,而展現效果(如PDF),則是通過預定義好的XSL-FO來實現的。XSL-FO是W3C的標準,正式的名稱是XSL,是XSL相關的三大組件/語言中的一個,另外兩個是XSLT和XPath。Apache的FOP是處理FO的眾多proecessor之一,相比iText,支持的輸出格式更多,對W3C相關標準支持度高,格式定義可以完全脫離具體的Java代碼,十分靈活,且控制力很強。缺點是大數據量時性能較差,默認中文支持不好。目前的版本是0.95。具體代碼:

          test.xml
          ?1?<?xml?version="1.0"?encoding="UTF-8"?>
          ?2?<source>
          ?3?????<title>
          ?4?????????FOP?Sample
          ?5?????</title>
          ?6?????<paragraph>
          ?7?????????測試abc中文123
          ?8?????</paragraph>
          ?9?</source>

          test.xsl
          ?1?<?xml?version="1.0"?encoding="UTF-8"?>
          ?2?<xsl:transform?version="1.0"
          ?3?????xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
          ?4?????xmlns:fo="http://www.w3.org/1999/XSL/Format">
          ?5?
          ?6?<xsl:template?match="/">
          ?7?????<fo:root>
          ?8???????<fo:layout-master-set>
          ?9?????????<fo:simple-page-master?master-name="A4-portrait"
          10???????????????page-height="29.7cm"?page-width="21.0cm"?margin="2cm">
          11???????????<fo:region-body/>
          12?????????</fo:simple-page-master>
          13???????</fo:layout-master-set>
          14???????<fo:page-sequence?master-reference="A4-portrait">
          15?????????<fo:flow?flow-name="xsl-region-body">
          16???????????<fo:block?font-family="WenQuanYi?Zen?Hei"?font-size="24pt">
          17?????????????<xsl:value-of?select="source/title"/>
          18???????????</fo:block>
          19???????????<fo:block?font-family="WenQuanYi?Zen?Hei"?text-indent="1cm">
          20?????????????<xsl:value-of?select="source/paragraph"/>
          21???????????</fo:block>
          22?????????</fo:flow>
          23???????</fo:page-sequence>
          24?????</fo:root>
          25?</xsl:template>
          26?
          27?</xsl:transform>

          fop-config.xml
          ?1?<?xml?version="1.0"?>
          ?2?<fop?version="1.0">
          ?3???<base>.</base>
          ?4???<source-resolution>72</source-resolution>
          ?5???<target-resolution>72</target-resolution>
          ?6???<default-page-settings?height="29.7cm"?width="21.0cm"/>
          ?7???<renderers>
          ?8?????<renderer?mime="application/pdf">
          ?9???????<filterList>
          10??????????<value>flate</value>
          11??????</filterList>
          12???????<fonts>??
          13?????????<directory>.</directory>
          14?????????<auto-detect/>
          15???????</fonts>
          16?????</renderer>
          17???</renderers>
          18?</fop>

          Formatter.java
          ?1?import?java.io.File;
          ?2?import?java.io.FileOutputStream;
          ?3?import?java.io.OutputStream;
          ?4?
          ?5?import?javax.xml.transform.Result;
          ?6?import?javax.xml.transform.Source;
          ?7?import?javax.xml.transform.Transformer;
          ?8?import?javax.xml.transform.TransformerFactory;
          ?9?import?javax.xml.transform.sax.SAXResult;
          10?import?javax.xml.transform.stream.StreamSource;
          11?
          12?import?org.apache.fop.apps.FOUserAgent;
          13?import?org.apache.fop.apps.Fop;
          14?import?org.apache.fop.apps.FopFactory;
          15?import?org.apache.fop.apps.MimeConstants;
          16?
          17?public?class?Formatter?{
          18?
          19?????public?static?void?main(String[]?args)?throws?Exception?{
          20?????????File?source?=?new?File("test.xml");
          21?????????File?specs?=?new?File("test.xsl");
          22?????????File?target?=?new?File("test.pdf");
          23?????????FopFactory?fopFactory?=?FopFactory.newInstance();
          24?????????fopFactory.setUserConfig("fop-config.xml");?//?讀取自定義配置
          25?????????FOUserAgent?foUserAgent?=?fopFactory.newFOUserAgent();
          26?????????OutputStream?out?=?new?FileOutputStream(target);
          27?????????out?=?new?java.io.BufferedOutputStream(out);
          28?????????try?{
          29?????????????System.out.print("Generating?PDF");
          30?????????????Fop?fop?=?fopFactory.newFop(MimeConstants.MIME_PDF,?foUserAgent,?out);
          31?????????????TransformerFactory?factory?=?TransformerFactory.newInstance();
          32?????????????Transformer?transformer?=?factory.newTransformer(new?StreamSource(specs));
          33?????????????Source?src?=?new?StreamSource(source);
          34?????????????Result?res?=?new?SAXResult(fop.getDefaultHandler());
          35?????????????transformer.transform(src,?res);
          36?????????????System.out.println("Done.");
          37?????????}?finally?{
          38?????????????out.close();
          39?????????}
          40?????}
          41?
          42?}

          效果:
          fop.png

          FOP的中文支持(其實是自定義字體支持),在0.94版本之前,十分有限,對每一個需要使用的TrueType字體,都需要生成一個metrics文件,在0.94和之后的版本,則沒有這個要求,且可以自動掃描系統字體和指定文件夾中的TTF字體。如果不配置中文字體,默認情況下,中文字符在PDF中將被處理成"#"。

          上面的示例代碼雖然簡單,但展示了FOP真正強大的地方,那就是控制力。這里篇幅有限,不可能全部特性都一一涉及,這個簡單的例子至少可以讓我們看到從原始的XML格式的數據,通過XSLT按照自定義的規則轉換成XSL-FO,最后輸出到PDF的過程,每一步都可以在Java代碼之外進行嚴格控制。

          以上是我對iText和FOP一些基本特點和用法的整理,它們各有特點,大家可以根據各自需要繼續深入研究,FOP和iText相結合也未嘗不可。希望能夠幫助到有需要的朋友。

          Feedback

          # re: iText vs FOP - Java動態生成PDF的兩個選擇  回復  更多評論   

          2008-10-06 08:43 by 123
          FOP沒有使用過,上個周就用iText做了一個PDF報表,還不錯,很強大。
          不過,郁悶的是,對網頁轉成PDF格式,都不怎么樣。
          估計是網頁格式里用了層的原因吧。

          # re: iText vs FOP - Java動態生成PDF的兩個選擇[未登錄]  回復  更多評論   

          2008-10-06 23:14 by shenguanghua
          itext我覺得最難的是排版,希望大哥能重點講些排版的例子

          # re: iText vs FOP - Java動態生成PDF的兩個選擇  回復  更多評論   

          2008-10-07 14:14 by innate
          IText在Html支持上,表格的寬度控制有bug,我用的是2.1.2不知道更新的有沒有解決

          # re: iText vs FOP - Java動態生成PDF的兩個選擇  回復  更多評論   

          2008-10-07 14:16 by innate
          IText中文支持也不是很好,曾經在中文問題上郁悶了很長時間。
          我用IText一般都是結合他的Html進行的,排版上問題不大,但是有些地方還是不好看。

          # re: iText vs FOP - Java動態生成PDF的兩個選擇  回復  更多評論   

          2008-10-08 00:50 by 大胃
          iText對中文的支持至少一方面自帶了中文字體,另外也可以通過normal體計算出粗體和斜體,不像FOP完全依賴字體文件。

          # re: iText vs FOP - Java動態生成PDF的兩個選擇  回復  更多評論   

          2008-11-04 11:15 by ALGO
          很多java的PDF都是以iText為底層的,iText的文檔中也提到,他們不打算做一個完整的html2pdf converter,并推薦ICE Browser SDK和另外一個什么來著,ice我試過,效果相對好很多,對普通html就能支持,不過可惜這個庫是要賣錢的。

          # re: iText vs FOP - Java動態生成PDF的兩個選擇  回復  更多評論   

          2008-11-04 12:05 by 大胃
          從對Java友好這個角度,iText確實不錯,但正因為這個特點,脫離了手寫的Java代碼,操作起來也就不是那么方便了。不像FOP,雖然不是100%標準實現,但思路還是清晰的,基本按照XSL-FO定義就能夠做出比較漂亮的排版,不需要寫任何Java代碼。文中的例子只是示意,其實FOP通過命令行就能玩轉,就算通過Java代碼去調用,這段Java也是寫一次就好,不管你格式多復雜。

          對于項目預算有限,或者由于其他原因不能或不希望采用商業解決方案的情況,iText和FOP都是不錯的選擇,看具體項目/工程需要吧。對于純輸出,以我實際使用看,FOP效果已經很好了,大不了多寫點XML,多畫點<fo:table/>,死不了。

          # re: iText vs FOP - Java動態生成PDF的兩個選擇  回復  更多評論   

          2008-11-04 13:35 by ALGO
          我正有一個項目需要做這種html2pdf的轉換,咨詢過ICE Browser, 但是他們說2010年后不再提供支持,看來生意做得也不好。此外有什么好的推薦嗎?

          # re: iText vs FOP - Java動態生成PDF的兩個選擇  回復  更多評論   

          2008-11-04 14:44 by 大胃
          現在很多商用軟件受到同類型開源軟件的沖擊都比較大,有些被迫開源,有些則慢慢淡出視線。

          曾經看過AntennaHouse的FO實現,好像還不錯,你可以看看:
          http://www.antennahouse.com/

          其實Apache的FOP已經很好了,主要是花時間熟悉FO語法。

          # re: iText vs FOP - Java動態生成PDF的兩個選擇  回復  更多評論   

          2015-04-14 16:23 by fop
          代碼拷貝運行報錯啊

          # re: iText vs FOP - Java動態生成PDF的兩個選擇  回復  更多評論   

          2015-04-14 16:25 by fop
          用0.95報錯的大概意思是還不支持。。。。。
          本地字庫的字體embet不進去。。。。
          主站蜘蛛池模板: 洪湖市| 通江县| 大冶市| 金门县| 达拉特旗| 华安县| 壶关县| 信阳市| 梨树县| 项城市| 巴彦淖尔市| 同心县| 马公市| 平安县| 清河县| 河西区| 东乡族自治县| 常州市| 肥西县| 济南市| 海伦市| 星座| 邛崃市| 滕州市| 苗栗市| 恩施市| 涿州市| 合作市| 汝州市| 高雄县| 济源市| 龙陵县| 鄂托克前旗| 前郭尔| 凤城市| 锦屏县| 台中县| 壶关县| 曲沃县| 保定市| 河曲县|