在Web应用中动态创建PDF文件(一)

2014-11-23 21:31:25 · 作者: · 浏览: 14

在一个最近的后勤项目中,客户要求我们建一个能让用户能从一个遗留系统查询出货信息的Web站点,有三个主要的需求:
1.出货信息必须以PDF文档的格式返回;
2.PDF文件必须能通过浏览器下载
3.PDF文件必须能用Adobe Acrobat Reader阅读;
尽管我们的团队有很多J2EE Web应用的开发经验,但在PDF文档处理上却没有多少经验。我们需要找一个能在服务器端Web应用里产生复杂的PDF文档的纯Java类库。最后,我们发现iText(http://www.lowagie.com/iText/)能完全满足我们的需要。

<iframe border="0" marginwidth="0" marginheight="0" src="http://adclient.163.com/html.ng/site=netease&affiliate=tech&cat=article&type=tvscreen&location=1" frameborder="no" width="360" scrolling="no" height="300">

1.iText类库

iText是一个创建和处理PDF文档的开源纯Java类库。Bruno Lowagie和Paulo Soares领导着这个项目。IText API能让Java开发人员以编程的方式创建PDF文档。iText提供了很多的特性:

支持PDF和FDF文档

各种页面尺寸

横向和竖向布局

页边距

表格

断字

页头

页脚

页码

条形码

字体

颜色

文档加密

JPEG,GIF,PNG和WMF图片

有序和无序列表

阴影

水印

文档模板
iText是一个开源库。在写本文的时候,iText可以在两个许可协议下使用:Mozilla Public License和LGPL。如果想了解详细信息,请参考iText站点。在本文中,你将会看到iText API的应用。我们将阐述如何在服务器端应用中使用iText和servlet动态生成PDF文档。

2.开始(Getting Started)

首先,你需要一个iText Jar文件。访问iText站点并下载最新的版本。在写本文时,最新的版本是使0.99。iText站点提供了API文档和一个全面的指南。
除了iText,我们还要用servlet.如果你不熟悉servlet,你可以通过Jason Hunter的书《Java Servlet Programming》来学习它。你需要一个J2EE应用服务器或可以独立运行的servlet引擎。开源软件Tomcat,Jetty和Jboss是不错的选择。下文假设你使用的是Jakarta Tomcat 4.1。

1.iText API

iText API简单易用。通过使用iText,你能创建自定义的PDF文档。iText库由下边的一些包组成:
com.lowagie.servlets
com.lowagie.text
com.lowagie.text.html
com.lowagie.text.markup
com.lowagie.text.pdf
com.lowagie.text.pdf.codec
com.lowagie.text.pdf.hyphenation
com.lowagie.text.pdf.wmf
com.lowagie.text.rtf
com.lowagie.text.xml
com.lowagie.tools
为了生成PDF文件,你只需要com.lowagie.text和com.lowagie.text.pdf两个包。
我们的例子使用了这些iText类:
com.lowagie.text.pdf.PdfWriter
com.lowagie.text.Document
com.lowagie.text.HeaderFooter
com.lowagie.text.Paragraph
com.lowagie.text.Phrase
com.lowagie.text.Table
com.lowagie.text.Cell
关键的类是Document和PdfWriter。在创建PDF文档时,你将经常使用这两个类。Document是PDF文档基于对象的描述。你可以通过调用Document类提供的方法往文档中加入内容。PdfWriter对象通过java.io.OutputStream对象与Document关联在一起。

3.在Web应用中使用iText

在设计阶段,你必须决定如何使用iText。我们使用了下边的技术开发了我们的Web应用。

1.A技术

在服务器文件系统上创建PDF文件。应用使用java.io.FileOutputStream把文件写到服务器文件系统上。用户通过HTTP GET方法下载该文件。

2.B技术

使用java.io.ByteArrayOutputStream在内存中创建PDF文件。应用通过servlet的输出流将该PDF文件字节发送到客户端。
由于应用不需要把文件写到文件系统上,这样能保证在集群服务环境中能正常工作,所以我更倾向于使用B技术。如果你的应用运行在集群环境中且服务器集群不提供会话亲和的功能,A技术可能会导致失败。

3.例子:PDFServlet

我们的例子应用由一个类组成:PDFServlet。这个servlet采用B技术。输出流OutputStream是java.io.ByteArryOutputStream。用ByteArrayOutputStream,PDF文档字节将存储在内存中。当PDFServlet接收到一个HTTP请求时,它将动态地生成一个PDF文档并将该文档发送到客户端。
PDFServlet类扩展了javax.servlet.http.HttpServlet类并导入了两个iText包:com.lowagie.text和com.lowagie.text.pdf。
doGet方法
大多数servlet覆盖了doPost和doGet方法中的一个方法。我们的servlet没有什么不同。PDFServlet类覆盖了doGet方法。该servlet将在接收到HTTP GET请求后生成一个PDF文件。
在核心部分,servlet的doGet方法做了如下的工作:
1.创建一个包含PDF文档字节的ByteArrayOutputStream对象;
2.在reponse对象上设置HTTP响应头内容;
3.得到servlet输出流;
4.把文档字节写到servlet的输出流中;
5.刷新servlet输出流;
generatePDFDocumentBytes方法
generatePDFDocumentBytes方法负责创建PDF文档。在这个方法中三个最重要的对象是Document对象,ByteArrayOutputStream对象和PdfWriter对象。PdfWriter使用ByteArrayOutputStream关联Document。
Document doc = new Document();
ByteArrayOutputStream baosPDF = new ByteArrayOutputStream();
PdfWriter docWriter = null;
docWriter = PdfWriter.getInstance(doc, baosPDF);
// ...
用ad