概述 Java Servlet 編程可以很方便地將 HTML 文件發送到客戶端的 Web 瀏覽器。然而許多站點還允許訪問非 HTML 格式的文檔,包括 Adobe PDF、Microsoft 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" ); |
(二)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來確定保存文當時的建議名稱。 |
(三)封裝非 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.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的文件。
接著打開Document:document.open()
3. 根據需要定義一個Table
//一個擁有十列的Table Table datatable = new Table(10); //定義Cell與Cell之間的距離為零 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類型就可以做到。