2009-06-19 115 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()); 

然后你的文件的字节内容写入。