iText vs FOP - Java动态生成PDF的两个选择


由于工作需要,今天简单的看了一下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 PDFdot.gif " );
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 PDFdot.gif " );
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相结合也未尝不可。希望能够帮助到有需要的朋友。

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值