[zt] http://topic.csdn.net/t/20061215/16/5233691.html
參考資料:
Web開發人員都有過這樣的疑問,如何讓一個文件,尤其是一個已知類型的文件,發送到客戶端,直接提示讓瀏覽者下載,而不是用與它相關聯的程序打開。以前我們最常用的辦法就是把這樣的文件加到鏈接上,這樣可以讓瀏覽者通過點擊鼠標右鍵的目標另存為來下載所鏈接的文件。但是,這樣有兩個不足的地方:
一是:如果瀏覽器能夠識別已下載文件的擴展名,則瀏覽器就會激活該擴展名所關聯的程序來打開所下載的文件。比如:在Windows平台上,如果用戶點擊的鏈接鏈接的是一個“.doc”文件的話,那么,瀏覽器就會啟動Microsoft Word應用程序來打開它。
二是:如果采用鏈接的辦法的話,任何能看到該鏈接的人都可以下載該文件,你雖然也可以對所下載的文件進行權限設置,但那樣做也不是很方便的。有時候我們需要更為靈活和富有彈性的方式,下面的程序能夠很方便地克服以上兩方面的不足。
這種辦法是可靠的,但你必須記住:沒有授權的用戶不能夠通過在瀏覽器地址欄里輸入文件的URL來取得該文件的下載權。所以,要下載的文件應該放到虛擬目錄之外的一個目錄里,比如:如果你的虛擬目錄是C:\Mengxianhui\Tomcat4\Website\MyApp的話,那么,存放在該目錄和該目錄下的任何子目錄下所有文件對因特網上的任何用戶都是可見的。要直接下載一個文件,我們需要做兩件事,第一件事是:設定響應的內容類為“application/octet-stream”,大小寫無關。第二件事是:設置HTTP的響應頭名字為:Content-Disposition,設定值為:attachment; filename = theFileName。這里的theFileName就是出現在文件下載對話框里的默認文件名,通常和所下載的文件名字相同,但也可以不同。下面,我們就平常最常用的JSP和ASP頁面來舉一個實際應用的例子。
TestFileDownload.JSP頁面的例子:
1 <% 2 // 得到文件名字和路徑 3 String filename = "MengxianhuiDocTest.doc "; 4 String filepath = "D:\\ "; 5 6 // 設置響應頭和下載保存的文件名 7 response.setContentType( "APPLICATION/OCTET-STREAM "); 8 response.setHeader( "Content-Disposition ", 9 "attachment; filename=\ " " + filename + "\ " "); 10 11 // 打開指定文件的流信息 12 java.io.FileInputStream fileInputStream = 13 new java.io.FileInputStream(filepath + filename); 14 15 // 寫出流信息 16 int i; 17 while ((i=fileInputStream.read()) != -1) { 18 out.write(i); 19 } 20 fileInputStream.close(); 21 out.close(); 22 %>
值得注意的是:在你要下載的文件內容里,除了文件的內容之外,不應該再附加有其它任何的字符,包括空格和回車換行符。我們有時在編寫代碼的時候,為了使代碼清晰可讀,往往會添加一些空格、制表符或者回車換行符,這樣雖然看起來比較清晰,但有時可能會得不到正確的結果。比如:
1 <%@ page import= "java.io.* " 2 %> <jsp:useBean id= "MyBeanFromMengxianhui " scope= "page " 3 class= "com.Mengxianhui.DownloadBean " /> 4 應該寫成這樣: 5 <%@ page import= "java.io.* " 6 %> <jsp:useBean id= "MyBeanFromMengxianhui " scope= "page " 7 class= "com.Mengxianhui.DownloadBean " />
TestFileDownload.ASP頁面的例子:
在ASP里,沒有提供從文件讀取文件流信息的方法,因此,為了得到文件的流信息,我們必須借助其他的工具,最簡單的就是編寫一個VB或C的DLL組件,讓組件返回文件的流信息。下面是一個用VB編寫的DLL的例子,工程名字為MengXHFileDownLoad,類模塊的名字為BinReadFromFile,類方法readBinFromFile如下:
Function readBinFromFile(ByVal bfilename As String) As Variant Dim fl As Long Dim FileNum As Long Dim binbyte() As Byte Dim binfilestr As String On Error GoTo errHandler FileNum = FreeFile Open bfilename For Binary As #FileNum fl = FileLen(bfilename) ReDim binbyte(fl) Get #FileNum, , binbyte Close #FileNum readBinFromFile = binbyte Exit Function errHandler: Exit Function End Function 把上面的代碼編譯成MengXHFileDownLoad.DLL,然后注冊即可使用。下面以直接下載一個When A Man Loves A Woman.mp3的MP3文件為例子,我們要編寫的ASP腳本代碼如下: <%@ Language=VBScript %> <% Response.buffer = TRUE Response.ContentType = "APPLICATION/OCTET-STREAM " Response.AddHeader "Content-Disposition ", "attachment;filename=When A Man Loves A Woman.mp3 " Dim varStream, oMyObject Set oMyObject = Server.CreateObject( "MengXHFileDownLoad.BinReadFromFile ") varStream = oMyObject.readBinFromFile( "E:\MengXianhui\Mp3\When A Man Loves A Woman.mp3 ") Response.BinaryWrite(varStream) Set oMyObject = Nothing Response.End %> 當我們運行上面的TestFileDownload.ASP文件時,瀏覽器會彈出一個文件下載的對話框,提示我們下載,而不是用默認的MP3播放器打開。 這種方法也可以把我們的ASP頁面生成的HTML源代碼保存成一個文件,下面的代碼會提示你把ASP執行的結果保存成Test.htm文件。具體的方法是: <% Response.ContentType = "APPLICATION/OCTET-STREAM " Response.AddHeader "Content-Disposition ", "attachment;filename=Test.htm " Response.write " <div style= 'background-color:navy;color:#FFFFFF '> 測試 </div> " Response.write " <a href= 'http://lucky.myrice.com '> " Response.write " <img src= 'http://lucky.myrice.com/back.jpg '> 【孟憲會之精彩世界】 </a> " Response.End %>
當我們的文件數目很少時,也可以直接在服務器端進行設置,讓這些文件直接下載。具體做法是:在Internet服務管理器里,選“屬性”項,然后選“HTTP Headers”標簽頁進行設置即可!!