2009-06-19 139 views
0

我在嘗試在JSP中提供zip文件時遇到問題。服務於zip的JSP損壞文件

壓縮文件在完成下載後總是損壞。我已經嘗試了幾種不同的閱讀和寫作方法,而且他們中的任何一個似乎都沒有辦法。

我想它可能是在ascii字符的某處添加文件將打開並顯示所有文件名,但我無法提取任何文件。

這裏是我的最新代碼:

<%@ page import= "java.io.*" %> 

<% 
    BufferedReader bufferedReader = null; 

    String zipLocation = "C:\\zipfile.zip"; 

    try 
    { 
     bufferedReader = new BufferedReader(new FileReader(zipLocation)); 
     response.setContentType("application/zip"); 
     response.setHeader("Content-Disposition", "attachment; filename=zipfile.zip"); 

     int anInt = 0; 
     while((anInt = bufferedReader.read()) != -1) 
     { 
      out.write(anInt); 
     } 
    } 
    catch(Exception e) 
    { 
     e.printStackTrace(); 
    } 
%> 

編輯: 我感動的代碼到一個servlet,它仍然沒有工作。我改變了周圍都是一些更多的東西,所以這裏的最新非工作代碼:

public void doGet(HttpServletRequest req, HttpServletResponse response) throws ServletException, IOException 
{ 
    try 
    { 
     String templateLocation = Config.getInstance().getString("Site.templateDirectory"); 

     response.setContentType("application/zip"); 
     response.setHeader("Content-Disposition", "attachment; filename=output.zip;"); 

     ByteArrayOutputStream baos = new ByteArrayOutputStream(); 
     BufferedOutputStream bos = new BufferedOutputStream(baos); 
     FileInputStream fis = new FileInputStream(templateLocation); 

     int len; 
     byte[] buf = new byte[1024]; 

     while ((len = fis.read(buf)) > 0) 
     { 
      bos.write(buf, 0, len); 
     } 

     bos.close(); 
     PrintWriter pr = response.getWriter(); 
     pr.write(baos.toString()); 
     pr.close(); 
    } 
    catch (Exception e) 
    { 
     e.printStackTrace(); 
    } 
} 

EDIT2:

這是我的實際工作servlet代碼。謝謝大家!

public void doGet(HttpServletRequest req, HttpServletResponse response) throws ServletException, IOException 
{ 
    try 
    { 
     String templateLocation = Config.getInstance().getString("Site.templateDirectory"); 

     response.setContentType("application/zip"); 
     response.setHeader("Content-Disposition", "attachment; filename=output.zip;"); 

     BufferedOutputStream bos = new BufferedOutputStream(response.getOutputStream()); 
     FileInputStream fis = new FileInputStream(templateLocation); 

     int len; 
     byte[] buf = new byte[1024]; 

     while ((len = fis.read(buf)) > 0) 
     { 
      bos.write(buf, 0, len); 
     } 

     bos.close(); 
    } 
    catch (Exception e) 
    { 
     e.printStackTrace(); 
    } 
} 

回答

6

拉鍊是二進制文件,因此不適合作爲字符數據傳輸。此外,代碼外的文字可能會破壞文件。

使用普通的vanilla servlet代替JSP。

+1

而且,看在上帝的份上,不要使用Reader來處理二進制數據。 – 2009-06-19 13:24:45

4

JSP爲輸出添加空格。我建議你把它移到一個servlet。

另外,你可以看看Strip whitespace from jsp output,但我不確定它不會影響ZIP輸出本身。

0

如果我沒有記錯的話,讀者通常用於字符流 - 你可能會嘗試更多的ByteArrayOutputStream的行嗎?另外,JSP可能確實會破壞其他人評論的輸出。

+0

我試過使用流和讀者,我得到了相同的結果。我想用一個普通的,香草的servlet再試一次。 – Jesse 2009-06-19 12:46:39

+0

我不知道你是否已經發現了這個,但是Sun的論壇提供了類似的線索:http://forums.sun.com/thread.jspa?threadID=5266941 – Jon 2009-06-19 13:11:51

2

這個確切代碼段中的問題在第二行 - JSP標籤之外有一個空行,它以HTML(即HTML源代碼中的空行)的形式發送到瀏覽器。

要非常小心從刪除任何東西,是不是在<%%>,尤其是空白(即使是終端一行!),還是照做其他地方使用servlet :)

+0

刪除所有空白區域也不起作用。 我想,因爲我把標題設置爲附件,它會忽略空格。 – Jesse 2009-06-19 12:51:27

0
bufferedReader = new BufferedReader(new FileReader(zipLocation)); 

除了Servlet/JSP問題,這一行將以100%的確定性破壞您的數據。它會嘗試使用默認的平臺編碼將二進制數據解釋爲文本,這意味着文件中大約一半的字節被替換爲「未知字符」。

字節和字符串不是一回事!

0

我也建議使用普通的servlet,並認爲Robert Munteanu's answer是正確的,但是您也可以在JSP中執行此操作。問題不是添加的空白,而是隱式變量「out」是JSPWriter的一個實例,Writer是用於字符的,而不是字節。嘗試使用response.getOutputStream()和正確的,這應該工作。你會得到一個異常,說別人已經得到了OutputStream,但你可以忽略它。

但正如我所說的,使用Servlet會更乾淨。

1

您的servlet代碼不起作用,因爲您正在輸出您的流到response.getWriter(),正如其他人指出的那樣,對於字符數據。我引述的Javadoc:

PrintWriter getWriter() throws IOException
返回一個PrintWriter對象,可以發送字符文本到客戶端。該PrintWriter的使用)由getCharacterEncoding(返回的字符編碼

不僅如此,但你甚至不寫字節數組Writer,你寫的ByteArrayOutputStream.toString(),也做了字符轉換的結果〜

你想用response.getOutputStream(),是這樣的:

BufferedOutputStream bos = new BufferedOutputStream(response.getOutputStream()); 

然後你的文件的字節內容寫入。