浅议基于Java的PDF文档生成

时间:2022-09-13 07:02:24

浅议基于Java的PDF文档生成

摘要:介绍了目前Java项目中生成PDF文档使用的几种主要工具,并对它们进行了简单的分析,介绍了一种新的工具Flying Saucer并描述了其特性,通过实例介绍了如何使用Flying Saucer动态生成PDF文档。

关键词:Java;PDF;Flying Saucer

中图分类号:TP319文献标识码:A文章编号:1009-3044(2011)24-5923-02

Discussion on Generating PDF Documents Based on Java

CUI Yong1,2, WANG Jian-xin1

(1.Information Science and Engineering School of Central South University, Changsha 410083, China; 2.Library of Central South University, Changsha 410083, China)

Abstract: This paper introduced several popular toolkits to generate PDF documents in Java project,and simply analyzed them,introduced a new toolkit named Flying Saucer and described the features, introduced how to generate dynamic PDF documents via Flying Saucer by given an example.

Key words: Java; PDF; Flying Saucer

1 问题的提出

作者在实际开发过程中遇到这样一个问题:如何把数据库中的相关数据组织起来生成PDF文档用来传递以及存档。该项目使用Java开发,需要一个基于Java的开源的免费的能生成丰富内容及样式的工具来实现。

经过多方面检索发现,目前在基于Java项目中,生成PDF的主要使用到以下几种工具:

1)iText[1]

iText是一个用于生成PDF文档的Java类库,使用iText的API可以很轻易的创建PDF文档,也可以将XML、Html文件转化为PDF文档。iText是一个基础类库,有些工具是基于iText完成的。

2)Jasper Report[2]

Jasper Report是开源的,完全使用Java写成的类库,它是基于iText的,但是比iText要完善很多。它有图形化的工具定义文档,然后通过不同的数据源来填充文档。

3)Adobe提供的FDF API[3]

Java FDF开发工具是Adobe公司提供的动态生成PDF文档的工具,它提供了一系列的API对PDF模板中的表单进行操作。

通过对以上三种工具的分析,可以将生成PDF文档归纳成两种途径:直接创建PDF文档;通过模板加数据进行整合生成PDF文档。直接创建PDF需要掌握很多API的细节,太过繁琐,而且不能直观的控制格式,不便于生成复杂的PDF文档。预定义PDF文档的样式,再用相关数据进行填充是较为理想的方法。iText可以将XML、Html转化为PDF文档,这就可以使用某些模板引擎(例如Freemarker、Velocity),先做好模板,再填充相关数据生成XML或Html文件,然后使用iText将其转化成为PDF文档。事实上,这样是可行的,但是存在一些问题,如iText不支持CSS以及无法识别某些HTML的标记,这使得PDF文档的表现力有所欠缺。Jasper Report是基于iText的,理论上来说应该做的比iText好,但是它的文档是需要付费的,而且需要对Jasper Report的每个元素都非常熟悉才能做出合适的模板。至于adobe的Java FDF开发工具,能够查到的相关资料很少,作者也没有找到相关的程序进行测试,不予以评价。在开源的框架下,有没有合适的方案达到要求,下面介绍一个基于Flying Saucer[2]的方案。

2 Flying Saucer介绍

Flying saucer是一个XML/CSS渲染器,它使用XML或XHTML文件作为输入,通过CSS控制格式和样式,渲染成图像、PDF文件或者使用Swing或SWT直接呈现在屏幕上(通过iText)。它由纯Java语言编写,完全兼容CSS2.1包括扩展属性,实现了部分CSS3特性,支持XHTML表单。

3 开发示例

总体思路:先根据所选的模板引擎(本项目中使用Freemarker)做好模板,调用引擎生成相应的html文件,再通过Flying Saucer提供的API将html文件转换成PDF文件,最后将此文件发送给客户端浏览器。

开发环境:MyEclipse 8、tomcat6、mysql6。

项目基于struts2框架,struts2默认提供Freemarker的jar包, Flying saucer可以从/p/flying-saucer/下载,目前的版本是R8。下面主要介绍项目相关文件的代码编写,包括模板test.ftl,generatePDF.action的实现类generatePDFAction.java,及struts.xml的配置。

首先编写模板文件test.ftl,按照Freemarker的相关规则将相关字段列出,并调整好格式。关于模板的制作非本文的重点,不作详细介绍,需要说明的是:CSS可以直接写到模板中,如果引用单独的CSS文件则需写成绝对地址(如:file:///d:/xxx/xx/xx.css);必须在CSS的body项中通过font-family指定模板中使用的中文字体,才能实现对中文的支持;通过CSS可以生成页眉与页脚。

完成后将test.ftl存到项目WebRoot下的WEB-INF目录中,在相关action的实现类中实现调用模板的并加载数据,将生成的html文件存储在字节输出流变量“baos”中,代码如下(关于数据库的调用未写出):

String ftlDIR = ServletActionContext.getServletContext().getRealPath("/WEB-INF");//取得存放模板位置的绝对路径

Configuration cfg=new Configuration();

cfg.setDefaultEncoding("UTF-8");

cfg.setDirectoryForTemplateLoading(new File(ftlDIR));//设置模板位置

cfg.setObjectWrapper(new DefaultObjectWrapper());

Template template = cfg.getTemplate("test.ftl");//调用模板

ByteArrayOutputStream baos = new ByteArrayOutputStream();

OutputStreamWriter osw = new OutputStreamWriter(baos);

template.process(this, osw);

osw.flush();

osw.close();

接着将字节输出流“baos”转化成PDF格式的字节输出流“pdfout”,然后将“pdfout”转化成字节输入流“ips”,准备输出至浏览器,并将文件名设置为“test.pdf”。

ByteArrayOutputStream pdfOut = new ByteArrayOutputStream();

ITextRenderer renderer = new ITextRenderer();

renderer.setDocumentFromString(baos.toString());

ITextFontResolver fontResolver = renderer.getFontResolver();

fontResolver.addFont("c:/windows/Fonts/simsun.ttc", BaseFont.IDENTITY_H, BaseFont.NOT_EMBEDDED);//加载CSS的body项中所指定的字体

renderer.layout();

renderer.createPDF(pdfOut);

this.ips = new ByteArrayInputStream(pdfOut.toByteArray());

baos.close();

pdfOut.close();

fileName = "test.pdf";

在struts.xml中对generatePDF的action节做如下的配置:

ips

application/pdf

inline;filename="${fileName}"

在浏览器中打开此项目的generatePDF.action,将会提示打开或保存“test.pdf”。

4 总结

这种方法由XHTML语言控制格式,由模板引擎来填充数据,最后在CSS的控制下生成丰富样式的PDF文档,它是开源的、免费的、完全基于Java的,可以无缝的集成到Java项目中,虽然它对某些特性的支持不完全,但总而言之,使用这种方法生成来生成PDF文档是满足需求的。接下来需要考虑的是,一旦访问量变大,其转换速度将会如何。

参考文献:

[1] 王鹏飞,杨和梅,丁俊松.利用Struts+iText在J2EE中实现PDF报表[J].现代电子技术,2006(22):46-48.

[2] downpour.介绍一个PDF的生成方案[EB/OL].(2009-11-03)./topic/509417.

[3] 游安弼,吴建军,黄志强.动态生成PDF文档的Java实现[J].计算机时代,2004(5):38-39.

上一篇:基于导频的MIMO-OFDM系统信道估计算法研究 下一篇:中职《Flash 动画制作与设计》学习领域课程的...