2011-06-29 134 views
44

一切工作正常,但只有當文件很小,大約1MB,當我用更大的文件,像20MB我的瀏覽器顯示它,而不是強制下載,我嘗試了很多標題到目前爲止,現在我的代碼看起來:如何強制瀏覽器下載文件?

PrintWriter out = response.getWriter(); 
String fileName = request.getParameter("filename"); 

File f= new File(fileName); 

InputStream in = new FileInputStream(f); 
BufferedInputStream bin = new BufferedInputStream(in); 
DataInputStream din = new DataInputStream(bin); 

while(din.available() > 0){ 
    out.print(din.readLine()); 
    out.print("\n"); 
} 

response.setContentType("application/force-download"); 
response.setContentLength((int)f.length()); 
response.setHeader("Content-Transfer-Encoding", "binary"); 
response.setHeader("Content-Disposition","attachment; filename=\"" + "xxx\"");//fileName); 


in.close(); 
bin.close(); 
din.close(); 
+0

設置內容類型應該這樣做。它是哪個瀏覽器? –

+0

哪個瀏覽器? Octet-stream應該是正確的答案,但IE的舊版本用於嘗試和「嗅探」內容類型,而不管Web服務器告訴它什麼 – Paolo

+0

chrome,ff 3.6,以及其他可能... – dieeying

回答

60

在將文件的內容寫入輸出流之後,您正在設置響應標頭。在設置標題的響應生命週期中,這很晚。正確的操作順序應該是首先設置標題,然後將文件的內容寫入servlet的輸出流。

因此,你的方法應該寫成如下(這將無法編譯,因爲它僅僅是一種表示):

response.setContentType("application/force-download"); 
response.setContentLength((int)f.length()); 
     //response.setContentLength(-1); 
response.setHeader("Content-Transfer-Encoding", "binary"); 
response.setHeader("Content-Disposition","attachment; filename=\"" + "xxx\"");//fileName); 
... 
... 
File f= new File(fileName); 

InputStream in = new FileInputStream(f); 
BufferedInputStream bin = new BufferedInputStream(in); 
DataInputStream din = new DataInputStream(bin); 

while(din.available() > 0){ 
    out.print(din.readLine()); 
    out.print("\n"); 
} 

的失敗原因是,它是可能通過實際發送的報頭這個servlet會和你打算髮送的不同。畢竟,如果servlet容器不知道哪些頭(在HTTP響應中出現在主體之前),那麼它可以設置合適的頭以確保響應是有效的;在寫入文件之後設置標題因此是徒勞的和冗餘的,因爲容器可能已經設置了標題。您可以通過使用Wireshark或HTTP調試代理(如Fiddler或WebScarab)查看網絡流量來確認此情況。

您也可以參考Java EE API文檔ServletResponse.setContentType理解這種行爲:

設置響應的內容類型被髮送到客戶端,如果響應尚未提交。給定的內容類型可能包含字符編碼規範,例如text/html; charset = UTF-8。如果在調用getWriter之前調用此方法,則只會根據給定的內容類型設置響應的字符編碼。

可以重複調用此方法來更改內容類型和字符編碼。 如果在提交響應之後調用此方法,則此方法無效。

...

+0

應用程序/強制下載是一個黑客,而不是一個標準:http://www.media-division.com/the-right-way-to-handle-file -downloads-in-php/ –

+0

@ChristopheRoussy,沒有人聲稱是這樣的。停止在這裏發送垃圾郵件。 –

+2

我想通知其他SO用戶有關這是一個黑客攻擊,以及它如何工作,因爲這是沒有提到任何地方,這是一個解釋:因此:http://stackoverflow.com/questions/10615797/utility-of-http-header -content-type-application-force-download-for-mobile –

3

這是一個PHP腳本,它與每一個我測試過的瀏覽器完美地解決了這個問題(因爲3.5,IE8 + FF,鉻)

header("Content-Disposition: attachment; filename=\"".$fname_local."\""); 
header("Content-Type: application/force-download"); 
header("Content-Transfer-Encoding: binary"); 
header("Content-Length: ".filesize($fname)); 

所以就我所看到的,你」重新做正確的事情。你有沒有檢查你的瀏覽器設置?

+0

我愛不釋手... – f1sh

+5

我猜想這是「你正在做的一切正確」,燒燬了你。接受的答案明確了什麼是不正確的。 –

+0

應用程序/強制下載是一個黑客,而不是一個標準 –

4

集內容類型和其他標題你寫的文件出來之前。對於小文件,緩衝內容,瀏覽器首先獲取標題。對於大數據來說,數據是第一位的。

+0

這是一個重要的信息位 - 學會了艱難的道路:) – ragebiswas

相關問題