我在尝试在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();
    }
}
有帮助吗?

解决方案

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

使用普通的vanilla servlet而不是JSP。

其他提示

JSP将whitespace添加到输出中。我建议你把它移到一个servlet。

或者,您可以查看从jsp输出中删除空白,但我不确定它是否会影响ZIP输出本身。

这个确切片段中的问题在第二行 - 您在JSP标记之外有一个空行,它以HTML格式发送到浏览器(即HTML源代码中的空白行)。

要小心删除<!> lt; %% <!> gt;中的任何内容,特别是空格(甚至是终端换行符!),或者按照其他地方的建议使用servlet:)

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

  

PrintWriter getWriter() throws IOException结果   返回可以将字符文本发送到客户端的PrintWriter对象。 PrintWriter使用getCharacterEncoding()

返回的字符编码

不仅如此,你甚至没有把字节数组写到Writer,你正在写ByteArrayOutputStream.toString()的结果,这也是一个字符转换〜

您想使用response.getOutputStream(),例如:

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

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

如果我没记错的话,读者通常会使用字符流 - 你可以尝试更多的ByteArrayOutputStream吗?此外,JSP确实可能破坏输出,正如其他人所评论的那样。

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

除了Servlet / JSP问题之外,这条线路正在以100%的确定性破坏您的数据。它将尝试使用默认平台编码将二进制数据解释为文本,这意味着文件中大约一半的字节将替换为<!> quot; unknown character <!>。;

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

我还建议使用普通的servlet并考虑 Robert Munteanu的回答是正确的,但你也可以在你的JSP中做到这一点。问题不是添加的空格,而是隐式变量<!> quot; out <!> quot;是JSPWriter的一个实例,Writer是用于字符,而不是用于字节。尝试使用 response.getOutputStream(),然后就可以了。你会得到一个异常,说别人已经有了OutputStream,但你可以忽略它。

但正如我所说,使用Servlet会更清晰。

许可以下: CC-BY-SA归因
不隶属于 StackOverflow
scroll top