Java动态生成PDF的两个开源工具-iText与FOP

    技术2025-02-28  35

    本文转自http://www.blogjava.net/sean/archive/2008/10/05/232577.html由于工作需要,今天简单的看了一下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  } 效果: 中文支持有默认的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 的中文支持(其实是自定义字体支持),在0.94版本之前,十分有限,对每一个需要使用的TrueType字体,都需要生成一个metrics文件,在 0.94和之后的版本,则没有这个要求,且可以自动扫描系统字体和指定文件夹中的TTF字体。如果不配置中文字体,默认情况下,中文字符在PDF中将被处 理成"#"。 上面的示例代码虽然简单,但展示了FOP真正强大的地方,那就是控制力。这里篇幅有限,不可能全部特性都一一涉及,这个简单 的例子至少可以让我们看到从原始的XML格式的数据,通过XSLT按照自定义的规则转换成XSL-FO,最后输出到PDF的过程,每一步都可以在Java 代码之外进行严格控制。 以上是我对iText和FOP一些基本特点和用法的整理,它们各有特点,大家可以根据各自需要继续深入研究,FOP和iText相结合也未尝不可。希望能够帮助到有需要的朋友。 

    最新回复(0)