Servlet输出PDF文档方法

来源:互联网 发布:暴走大事件被停播知乎 编辑:程序博客网 时间:2024/05/11 03:17

概述 Java Servlet 编程可以很方便地将 HTML 文件发送到客户端的 Web 浏览器。然而许多站点还允许访问非 HTML 格式的文档,包括 Adobe PDFMicrosoft Word  Micorsoft Excel 等。事实上这些非 HTML 格式只要能用 MIME 类型表示,就可以利用 servlet 来发送。本文将以 PDF为例,向你介绍如何使用 servlet 传送非 HTML 格式文件及该文件是如何在服务器端用Java生成的。 

你只要将文件写到servlet 的输出流中,就可以利用 servlet 在浏览器中打开一个文件。首先从获得 servlet 的输出流开始: 

ServletOutputStream out = res.getOutputStream(); 

互联网上使用 MIME (multipurpos Internet mail extension 多目的互联网邮件扩展协议)来传送混合格式、多媒体和二进制数据文件。如果要在 servlet  response 对象中打开某个文档,就必须设置该文档的 MIME 类型。 

Web客户端发送PDF文档 
(
)MIME类型 
Web 
浏览器使用 MIME 类型来识别非 HTML 文档,并决定如何显示该文档内的数据。将插件 (plug-in)  MIME 类型结合使用,则当 Web 浏览器下载 MIME 类型指示的文档时,就能够启动相应插件处理此文档。某些 MIME 类型还可以与外部程序结合使用,浏览器下载文档后会启动相应的外部程序。 

MIME 
类型非常有用。它们允许 Web 浏览器处理不同格式的文档,却不需要事先嵌入相关知识。Java Servlets 可以使用 MIME 类型来向浏览器传送非 HTML 文件,比如 Adobe PDF  Micorsoft Word。使用正确的 MIME 类型能够保证这些非 HTML 文件被正确的插件或外部程序显示。 

PDF 
文件的 MIME 类型是 "application/pdf"。要用servlet 来打开一个 PDF 文档,需要将 response 对象中 header  content 类型设置成 "application/pdf": 

// PDF 
文件的 MIME 类型 
res.setContentType( "application/pdf" ); 
//也可以通过下面的方式来设置

response.setHeader("Content-type", "application/pdf");
(
)Content disposition 
HTTP response header
中的content-disposition 允许 servlet 指定文档表示的信息。使用这种header ,你就可以将文档指定成单独打开(而不是在浏览器中打开),还可以根据用户的操作来显示。如果用户要保存文档,你还可以为该文档建议一个文件名。这个建议名称会出现在 Save As 对话框的文件名栏中。如果没有指定,则对话框中就会出现 servlet 的名字。在 servlet 中,你需要将 header 设置成下面这样: 

res.setHeader("Content-disposition", 
"attachment; filename=" + 
"Example.pdf" ); 
// attachment -
因为不希望在浏览器中直接打开它,而是利用Adobe Acrobat 
// 
可以通过设置default file name来确定保存文当时的建议名称。 
//response.setHeader("Content-Disposition", "inline; filename=report.pdf");
(三)封装非 HTML 文档 
完成上述工作后,剩下的就非常简单了。你需要根据待传送文件的名字,创建一个 java.net.URL 对象。交给 URL 构造器的字符串必须是指向该文件的一个有效 URL 地址。在这里,我要打开本地的PDF文档: 

String fileURL = "http://localhost/aboutadobe/careeropp/pdfs/tables.pdf; 

URL 
字符串也可以类似于 http://www.gr.com/pub/somefile.doc  http://www.gr.com/pub/somefile.xls。但必须确保待传送文件类型与先前在 HTTP response 对象中设置的 MIME 类型一致。 

(四)其他 
开始阅读传送的文档之前,首先要从 URL 对象中获得输入流 InputStream,用 BufferedInputStream  InputStream 封装起来。 

BufferedInputStreambis = newBufferedInputStream(url.openStream()); 

一旦你完成上述操作,就只要简单地将 InputStream 中的字节,写入到 servlet 的输出流 OutputStream 中: 

BufferedOutputStreambos = new BufferedOutputStream(out); 

byte[] buff = new byte[2048]; 
intbytesRead; 

// 
一个简单的读写循环 
while(-1 != (bytesRead = bis.read(buff, 0, buff.length))) { 
bos.write(buff, 0, bytesRead); 



在最后的代码块中,关闭这些流 ,如:bos.close(); 

PDF
文档在服务器端的生成 
利用iText040工具包可以很方便的输出一个十分漂亮的PDF文档。 

1.Document
的创建 
Document document=new Document(p0, p1, p2, p3, p4) 

其中,p0为页面的大小,如 PageSize.A4; p1?p4分别描述上下左右页边空白。 

2. 
构造复写器 
PdfWriter.getInstance(document, new FileOutputStream("tables.pdf")) 

执行程序后,将在当前目录下生成一个名为tables.pdf的文件。 

接着打开Documentdocument.open() 

3. 
根据需要定义一个Table 
//
一个拥有十列的Table 
Table datatable = new Table(10); 
//
定义CellCell之间的距离为零 
datatable.setCellpadding(0); 
//
定义Cell的间隔 
datatable.setCellspacing(3); 
//
使Table没有边框 
datatable.setBorder(Rectangle.NO_BORDER); 
//
定义每一列的宽度 
intheaderwidths[] = {10, 30, 15, 15, 5, 5, 5, 5, 5, 5}; 
datatable.setWidths(headerwidths); 
datatable.setWidth(100); 

4.
字体的定义: 
BaseFont bf = BaseFont.createFont(String name, String encoding, boolean embedded) 

name”为字体名,“encoding”为编码名称。 

5. Cell
的定义 
Cell cell = new Cell(new Phrase("String string",f)); 

String
Cell中要显示的内容。另外有很多方法来控制Cell,其中比较常用的几个方法如下: 

cell.setBorder(int value) 

根据经验,value值对应的边框形状见下图: 

图例 Value 整数值 
Rectangle.ALIGN_BOTTOM 6 
Rectangle.ALIGN_BASELINE 7 
Rectangle.ALIGN_CENTER 1 
Rectangle.ALIGN_JUSTIFIED 3 
Rectangle.ALIGN_MIDDLE 5 
Rectangle.ALIGN_RIGHT 2 
Rectangle.ALIGN_TOP 4 

cell.setColspan(int value)
 cell.setRowspan(int value)分别定义了cell所占的列和行。 

值得注意的是:一行中各cell所占列的总和一定要严格符合构造table时定义的列数。 

cell.setHorizontalAlignment(int value)
cell.setVerticalAlignment(int value)分别确定该cell将处在水平及竖直方向上的位置。 

最后,将cell加入到table中去:table.addCell(Cell cell) 

6.table
加到document中去,并关闭document 

document.add(table); 
document.close(); 

小结 
正如你所读到的,利用iText040编写一个可以输出PDF文档的JavaBean。接着,再通过sevlet将它输出到客户端,相当简单。只要你使用适当的方法,设置正确的MIME类型就可以做到。

原创粉丝点击