[摘 要]:Java不依賴平臺的特點使得它受到了廣泛的關注,許多和java相關的優(yōu)秀技術不斷出現(xiàn),JSP(Java Server Page)就是其中之一。我們應用JSP能夠開發(fā)出動態(tài)的、高性能的、安全的跨平臺的網(wǎng)站。在網(wǎng)站中實現(xiàn)文件的上傳、下載的技術也非常普遍。
[關鍵詞]:OutoutStream(輸出流) InputStream(輸入流) JavaBeans response MIME(Multipurpose Internet Mail Extensions,多目的Internet郵件擴展)
引言
當今利用JSP語言制做網(wǎng)站的技術備受青睞。因此我們的畢業(yè)設計也就選擇了應用JSP開發(fā)了我們的“軟件開發(fā)小組輔助交流系統(tǒng)”。我在這里簡單地就文件下載以及如何統(tǒng)計下載次數(shù)談論一下自己的想法。
1 介紹一下Java中的InputStream(輸入流)和OutputStream(輸出流)
java.io包提供大流量的流類。Java的I/O流提供一條通道程序,可以使用這條通道把源中的數(shù)據(jù)傳送到目的地。我們把輸入流的指向稱作源,程序從指向源的輸入流中讀取源中的數(shù)據(jù)。而輸出流的指向是數(shù)據(jù)要去的一個目的地,程序通過向輸出流中寫入數(shù)據(jù)把信息傳送到目的地。請看下面的輸入流和輸出流工作示意圖:
2 闡述JSP中實現(xiàn)文件下載可以使用的幾種方法:
通過對JSP的學習和在此次畢業(yè)設計過程中的經(jīng)驗,我發(fā)現(xiàn)在JSP中實現(xiàn)文件的下載可以使用下面的3種辦法。
2.1使用超級鏈接直接連接到文件的物理地址
利用這種辦法實現(xiàn)對文件的下載很簡單,我們可以從數(shù)據(jù)庫中讀出每一個文件的相關信息以列表的形式輸出到網(wǎng)頁上。然后我們可以選擇其中的一項信息做成超級鏈接直接連接到這個文件所在的物理地址。程序代碼如下:
其中(String)rs.getString(“file_name”)是我們要下載的文件的名字。而<%=filename%>就是輸出到網(wǎng)頁中的一個變量名,這里是文件名。就是它直接超級鏈接到這個物理文件所在的路徑(這里用的是相對路徑)。那么當我們點擊這個超級鏈接時便可以對該文件進行下載了。這種辦法很簡單,但是它存在一些缺陷,通常情況下當我們左鍵點擊該超級鏈接時就會直接打開該文件,因為我們訪問的是遠端的服務器上的文件,所以速度特別慢。還有,這種下載文件的方法我們不容易統(tǒng)計下載次數(shù)。所以,我們沒有采用這種辦法做文件下載。
2.2使用http://www.jspsmart.com網(wǎng)站提供的SmartUpload組件實現(xiàn)文件下載
這種方法也非常簡單,我們只要登陸這個站點下載這個SmartUpload組件,因為我們是利用JSP開發(fā)我們的系統(tǒng),而且這個組件是一個編譯好的JavaBeans,所以我們必須把這個組件放在我們建好的web站點下的虛擬目錄下的WEB-INF文件夾下的classes文件夾下,然后我們只要用文本編輯器編寫以下幾行代碼就可以輕松實現(xiàn)文件下載。
<%@ page contentType=\"text/html;charset=gb2312\" import=\"com.jspsmart.upload.*\" %>
<%
// 新建一個SmartUpload對象
SmartUpload su = new SmartUpload();
// 初始化
su.initialize(pageContext);
// 設定contentDisposition為1以禁止瀏覽器自動打開文件,
//若不設定,擴展名為doc時,瀏覽器將自動用word打開它。
//若不設定,擴展名為pdf時,瀏覽器將用acrobat打開。
su.setContentDisposition(1);
// 下載文件
su.downloadFile(\"/upload/被下載的文件.doc\");
%>
我們利用這個JavaBeans組件可以很輕松地實現(xiàn)文件的上傳和下載。
2.3使用Java中的OutputStream(輸出流)對文件進行下載
JSP內(nèi)置對象response調(diào)用方法getOutputStream()可以獲取一個指向客戶的輸出流,服務器將文件寫入這個流,客戶端就可以下載這個文件了。當JSP頁面提供下載功能時,應當使用response對象向客戶端發(fā)送HTTP頭信息,說明文件的MIME(Multipurpose Internet Mail Extensions,多目的Internet郵件擴展)類型,這樣客戶端的瀏覽器就會調(diào)用相應的外部程序打開下載的文件。例如,Ms-Word文件的MIME類型是application/msword, pdf文件的MIME類型是application/pdf。還有幾點特別要注意的是,執(zhí)行下載的頁面,在JSP代碼范圍之外(即<% ... %>之外),不能包含任何HTML代碼、空格、回車或換行等字符,如果有的話將不能正確下載。因為它影響了返回給瀏覽器的數(shù)據(jù)流,導致解析出錯。我在一開始編寫下載這部分代碼時,就出現(xiàn)了這種錯誤。當我在瀏覽器里打開這個JSP頁就提示有這種OutputStream錯誤,后來我還是通過上網(wǎng)查找資料找到了問題的癥結(jié)所在,我把所有的HTML代碼都刪除,最后問題終于解決了。
例如下面的程序(loadfiles.jsp)就是用這種辦法實現(xiàn)文件下載的。
<%@ page contentType=\"text/html;charset=gb2312\" %>
<%@ page import=\"java.io.*\"%>
<%@ page import=\"java.sql.*\"%>
<%
/****** 特別注意:本程序之前不能有任何空格或換行符??! 整個JSP中不能使用任何html標記??! ******/
String name=\"\";
int newloadtimes=0;
String id=request.getParameter(\"fname\");
String sql1=\"select file_name,load_times from file where file_name='\"+id+\"'\";
ResultSet rs=conn.executeQuery(sql1);
if(rs.next())
{
name=rs.getString(\"file_name\");
newloadtimes = Integer.parseInt(rs.getString(\"load_times\"))+1;
}
//修改下載次數(shù)
out.print(id);
String sql2=\"update file set load_times=\"+newloadtimes+\" where file_name='\"+id+\"'\";
conn.executeUpdate(sql2);
OutputStream o = response.getOutputStream();
Byte[] temp = name.getBytes(\"ISO-8859-1\");
name = new String(temp,\"utf-8\");
String filedir=\"E:/system/FILES/\";
//提示客戶端保存還是打開文件的對話框如果取消下面這一句代碼客戶端瀏覽器將調(diào)用相應的外部程序,在當前位置直接打開文件
response.setHeader(\"Content-Disposition\", \"attachment;filename=\" + new String(name.getBytes(),\"ISO-8859-1\"));
response.setContentType(\"text/html;charset=utf-8\");
FileInputStream in = new FileInputStream(filedir+name);
int bytesRead;
//輸出文件用的字節(jié)數(shù)組,每次發(fā)送4k字節(jié)到輸出流
Byte[] buf = new byte[4 * 1024];
while ( (bytesRead = in.read(buf))!= -1)
{
o.write(buf, 0, bytesRead);
}
in.close();
o.close();
%>
我在此次畢業(yè)設計中就是應用這種方法實現(xiàn)文件下載的。我個人認為這種方法較前兩種方法比較合適。通過對這種方法的學習和應用,我理解了Java中InputStream(輸入流)和OutputStream(輸出流)這兩個類以及InputStream從源中讀取數(shù)據(jù)的方法和OutputStream向輸出流寫入數(shù)據(jù)的方法。
3 實現(xiàn)統(tǒng)計文件的下載次數(shù)
我們?yōu)榱酥烙脩魧δ男┪募信d趣,用戶經(jīng)常頻繁地下載哪些文件,因此我們要統(tǒng)計文件的下載次數(shù),這樣我們就可以了解用戶的需求,以便可以更好地為用戶服務。例如上面的代碼不但實現(xiàn)了文件的下載,而且還可以統(tǒng)計文件被下載的次數(shù)。上面的程序(loadfiles.jsp)里的以下幾行代碼就實現(xiàn)了統(tǒng)計文件下載的次數(shù)。
String name=\"\";//下載的文件的名字
int newloadtimes=0;//文件下載次數(shù),初值為0
String id=request.getParameter(\"fname\");//上一頁傳過來的值(文件名)
//下面的SQL語句提取出下載的文件的文件名以及下載次數(shù)
String sql1=\"select file_name,load_times from file where file_name='\"+id+\"'\";
ResultSet rs=conn.executeQuery(sql1);//執(zhí)行查詢
if(rs.next())
{
name=rs.getString(\"file_name\");
newloadtimes = Integer.parseInt(rs.getString(\"load_times\"))+1;//把下載次數(shù)加1
}
//修改下載次數(shù)
out.print(id);//輸出上一頁傳過來的文件名,進行測試
String sql2=\"update file set load_times=\"+newloadtimes+\" where file_name='\"+id+\"'\";
//更新表把新的下載次數(shù)寫入數(shù)據(jù)表
conn.executeUpdate(sql2);//執(zhí)行更新
4總結(jié)
通過此次畢業(yè)設計的鍛煉,我掌握了怎樣實現(xiàn)文件的下載和如何統(tǒng)計下載次數(shù)的方法,同時我還學到了很多JSP的其它知識,基本上掌握了利用JSP開發(fā)網(wǎng)站的編程思想。領會到了JSP中最核心的內(nèi)容之一--JavaBeans的優(yōu)點。JavaBeans可以實現(xiàn)代碼的重復利用;易編寫、易維護、易使用;能夠運行在任何已經(jīng)安裝了Java的平臺,而且不用重新編譯。例如我們開發(fā)這個“輔助交流系統(tǒng)”時訪問數(shù)據(jù)庫的各項操作就做成了一個JavaBeans。應用起來非常方便。
致謝:在此次畢業(yè)設計過程中和畢業(yè)論文的寫作過程中,馬季骕和蘇貴斌老師給予了精心的指導并且提出了寶貴的意見,為我提供了極大的幫助,在這里向二位老師表示衷心的感謝!
參考文獻:
[1]耿祥義、張躍平.《JSP使用教程》清華大學出版社2003年
[2]孫一林、彭波.《Java數(shù)據(jù)庫編程實例》清華大學出版社2003年
[3]林邦杰《JSP交互網(wǎng)站實務精典》北京中國青年出版社2001年