我在尝试在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();
}
}
答案 0 :(得分:6)
Zips是二进制文件,因此不适合作为字符数据传输。此外,代码外的文本可能会损坏文件。
使用普通的vanilla servlet而不是JSP。
答案 1 :(得分:4)
JSP将whitespace添加到输出中。我建议你把它移到一个servlet。
或者,您可以查看Strip whitespace from jsp output,但我不确定它是否会影响ZIP输出本身。
答案 2 :(得分:2)
这个确切片段中的问题在第二行 - 您在JSP标记之外有一个空行,它以HTML格式发送到浏览器(即HTML源代码中的空白行)。
要小心删除任何不在&lt; %%&gt;中的内容,特别是空格(甚至是终端换行符!),或者按照其他地方的建议使用servlet:)
答案 3 :(得分:1)
您的servlet代码不起作用,因为您要将流输出到response.getWriter()
,正如其他人指出的那样是字符数据。我引用Javadoc:
返回的字符编码
PrintWriter getWriter() throws IOException
返回可以将字符文本发送到客户端的PrintWriter对象。 PrintWriter使用getCharacterEncoding()
不仅如此,你甚至没有把字节数组写到Writer
,你正在编写ByteArrayOutputStream.toString()
的结果,它也进行了字符转换〜
您想使用response.getOutputStream(),例如:
BufferedOutputStream bos = new BufferedOutputStream(response.getOutputStream());
然后将文件的字节内容写入其中。
答案 4 :(得分:0)
如果我没记错的话,读者通常会使用字符流 - 你可以尝试更多的ByteArrayOutputStream吗?此外,JSP确实可能破坏输出,正如其他人所评论的那样。
答案 5 :(得分:0)
bufferedReader = new BufferedReader(new FileReader(zipLocation));
除了Servlet / JSP问题之外,这条线路正在以100%的确定性破坏您的数据。它将尝试使用默认平台编码将二进制数据解释为文本,这意味着文件中大约一半的字节将替换为“未知字符”。
字节和字符串不是一回事!
答案 6 :(得分:0)
我还建议使用普通的servlet并将Robert Munteanu's answer视为正确,但您也可以在JSP中执行此操作。问题不是添加的空格,而是隐式变量“out”是JSPWriter的一个实例,而Writer是用于字符,而不是字节。尝试使用 response.getOutputStream(),然后就可以了。你会得到一个异常,说别人已经有了OutputStream,但你可以忽略它。
但正如我所说,使用Servlet会更清晰。