2009-12-20 55 views
0

我在JSP頁面中列出了一些可以由用戶下載的文件。 Thoses文件不在本地服務器上,它們位於遠程文件服務器上。JSP下載 - application/octet-stream

當用戶點擊下載文件時,網絡服務器通過TCP連接到文件服務器。 Web服務器下載文件併爲客戶端創建HTTP響應。

這裏是我的代碼:

<%@page language="java"%> 
<%@page import="sun.misc.Request"%> 
<%@page import="listing.ClientTCPStockage"%> 
<%@page import="java.net.InetAddress"%> 

<% 
out.clearBuffer(); 

String nomFichier = request.getParameter("fichier"); 
String adresseStockage = request.getParameter("adresseStockage"); 

ClientTCPStockage clientStockage = new ClientTCPStockage(InetAddress.getByName(adresseStockage), 2004); 
byte donneeFichier[] = clientStockage.getDonneesFichier(nomFichier); 

response.setHeader("Content-Disposition", "attachment;filename=\"" + nomFichier + "\""); 
response.setHeader("Content-Type", "application/octet-stream;"); 
response.setHeader("Accept-Ranges", "bytes"); 
response.setHeader("Content-Length", String.valueOf(donneeFichier.length)); 

for(int i = 0; i < donneeFichier.length; i++){ 
    out.write(donneeFichier[i]); 
} 
%> 

這是工作完全正常的基於文本的文件,如.csv或正常.TXT 但它不用於其他類型的像MP3播放或.jpeg工作..文件最終損壞。

我覺得這是我的編碼中的問題,但我找不到在哪裏..

這裏是HTTP標頭響應:

HTTP/1.x 200 OK 
Server: Apache-Coyote/1.1 
Content-Disposition: attachment;filename="test.mp3" 
Accept-Ranges: bytes 
Content-Type: application/octet-stream; 
Content-Length: 5387668 
Date: Sun, 20 Dec 2009 18:52:18 GMT 

感謝。

+0

ClientTCPStockage連接到文件服務器並以byteArray形式抓取文件。在這一點上,內容是有效的,因爲當我試圖將它作爲一個文件放回硬盤驅動器時,它完美地工作。 當我將它輸出爲HTTP響應時,數據會被破壞 –

+0

可能是dup:請參閱http://stackoverflow.com/questions/1776142/getoutputstream-has-already-been-called-for-this-response/1776161#1776161對於從JSP寫入'OutputStream'的危險。 – skaffman

回答

4

如果強行使用JSP(而不是一個Servlet),你可以看看this how-to

它使用ServletOutputStream,這是更適合的二進制內容,而不是JspWriter

另請注意修剪空格的設置。

+1

啊是的,'out'不直觀地指'Writer',而不是'OutputStream'。 – BalusC

+0

謝謝!它完美的工作! :) –

4

JSP是一種視圖技術。在腳本<% %>之外的所有東西都會被打印給響應,包括空行字符如換行符。它肯定會損壞二進制文件。

您可以修剪JSP文件中的空白,但是自十年以來,現在認爲bad practice是scriptlet,因此不鼓勵。原始Java代碼屬於Java類,不屬於JSP文件。真正的解決方案是爲此使用Servlet

創建一個類extends HttpServlet,實現doGet()方法,從JSP文件中的Java代碼進入這個方法,在一定url-pattern映射這個servlet和你的問題應該會消失。您可以找到here a 基本這樣一個servlet的例子。

除了這個問題,你要將整個文件存儲在byte[]而不是InputStream中。我不確定你的ClientTCPStockage究竟在做什麼,但我建議修復這個問題。這是因爲byte[]的每個byte都有效地節省了JVM內存的一個字節。想象一下你有128MB的JVM內存,並且有超過10個用戶同時運行這段代碼並且文件大於12.8MB。是的,OutOfMemoryError

+0

+1我沒有看到空白。儘管我同意Servlet更清潔並且是最佳實踐,但我們至少應該提到OP可以簡單地將前6行壓縮在一起,就像這樣:<%@ page language =「java」%><%@ page import =「 sun.misc.Request「%><%@ page import =」listing.ClientTCPStockage「%><%@ page import =」java.net.InetAddress「%><%',jsp頁面可能會按原樣運行。有些日子,你必須完成工作,而不必將所有jsps重構爲Servlet。 :) – Asaph

+0

另外,請確保'%>'後面的文件末尾沒有尾隨空格。 – Asaph

+0

白色空間不應該是一個問題,因爲我打電話out.clearBuffer()在開始 –