【问题标题】:JSP to serve a zip corrupts the file提供 zip 的 JSP 损坏了文件
【发布时间】:2009-06-19 12:37:15
【问题描述】:

我在尝试在 JSP 中提供 zip 文件时遇到问题。

zip 文件在下载完成后总是损坏。我尝试了几种不同的阅读和写作方法,但似乎都没有奏效。

我认为它可能在某处添加了 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();
    }
}

【问题讨论】:

    标签: java jsp servlets zip


    【解决方案1】:

    Zip 是二进制文件,因此不适合作为字符数据传输。代码之外的文本也可能损坏文件。

    使用普通的 servlet 代替 JSP。

    【讨论】:

    • 而且,看在上帝的份上,不要使用 Reader 来处理二进制数据。
    【解决方案2】:

    JSP 在输出中添加空格。我建议您将其移至 servlet。

    或者,您可以查看 Strip whitespace from jsp output ,但我不确定它是否会影响 ZIP 输出本身。

    【讨论】:

      【解决方案3】:

      这个确切的 sn-p 中的问题在于第二行 - 您在 JSP 标记之外有一个空行,它作为 HTML 发送到浏览器(即 HTML 源代码中的一个空行)。

      要非常小心地删除任何不在 中的内容,尤其是空格(甚至是终端换行符!),或者按照其他地方的建议并使用 servlet :)

      【讨论】:

      • 删除所有空白也不起作用。我想既然我将标题设置为附件,它会忽略空格。
      【解决方案4】:

      您的 servlet 代码不起作用,因为您将流输出到 response.getWriter(),正如其他人指出的那样,这是针对 字符数据。我引用了 Javadoc:

      PrintWriter getWriter() throws IOException
      返回一个可以向客户端发送字符文本的 PrintWriter 对象。 PrintWriter 使用 getCharacterEncoding() 返回的字符编码

      不仅如此,你甚至没有将字节数组写入Writer,你正在写入ByteArrayOutputStream.toString()的结果,它还进行了字符转换~

      你想使用 response.getOutputStream(),类似于:

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

      然后将文件的字节内容写入其中。

      【讨论】:

        【解决方案5】:

        如果我没记错的话,阅读器通常用于字符流 - 您可能会尝试更多类似 ByteArrayOutputStream 的东西?此外,正如其他人所评论的那样,JSP 确实可能会破坏输出。

        【讨论】:

        • 我尝试过使用流和阅读器,得到了相同的结果。我想我会用一个普通的、普通的 servlet 再试一次。
        • 我不知道你是否已经找到了这个,但是 Sun 的论坛提供了一个类似的主题:forums.sun.com/thread.jspa?threadID=5266941
        【解决方案6】:
        bufferedReader = new BufferedReader(new FileReader(zipLocation));
        

        除了 Servlet/JSP 问题之外,这行代码 100% 肯定会损坏您的数据。它将尝试使用默认平台编码将二进制数据解释为文本,这意味着文件中大约一半的字节被替换为“未知字符”。

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

        【讨论】:

          【解决方案7】:

          我还建议使用一个普通的 servlet,并认为Robert Munteanu's answer 是正确的,但您也可以在您的 JSP 中执行此操作。问题不在于添加的空格,而是隐式变量“out”是 JSPWriter 的一个实例,而 Writer 用于字符,而不是字节。尝试使用 response.getOutputStream() 并就可以了,应该可以。您将收到一个异常,说明其他人已经获得了 OutputStream,但您可以忽略它。

          但正如我所说,使用 Servlet 会更干净。

          【讨论】:

          • 我已将我的 servlet 代码添加到问题中,因为我仍然无法让它工作。
          猜你喜欢
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 2018-03-20
          • 2014-02-25
          • 1970-01-01
          • 1970-01-01
          相关资源
          最近更新 更多