英文:
Corrupted zip file using ZipOutputStream
问题
我试图创建一个ZIP文件,以便能够通过HTTP发送多个文件。
我的问题是生成的ZIP文件在发送之前和之后都是“损坏”的。问题是,我无法找到我做错了什么,因为控制台内没有错误消息。
那么,有人知道为什么我的生成的ZIP文件会损坏吗?
这是我的代码:
OutputStream responseBody = t.getResponseBody();
ByteArrayOutputStream baos = new ByteArrayOutputStream();
ZipOutputStream zos = new ZipOutputStream(baos);
int counter = 1;
for (PDDocument doc : documents)
{
ZipEntry zipEntry = new ZipEntry("document" + counter);
zos.putNextEntry(zipEntry);
ByteArrayOutputStream docOs = new ByteArrayOutputStream();
doc.save(docOs);
docOs.close();
zos.write(docOs.toByteArray());
zos.closeEntry();
zos.finish();
zos.flush();
counter++;
}
zos.close();
baos.close();
responseBody.write(baos.toByteArray());
responseBody.flush();
感谢您的帮助!
英文:
I'm trying to create a zip file to be able to send multiple files over http.
My issue is that the Zip file that is generated is "corrupted" before and after the file has been send. The issue is i'm not able to find what i did wrong as i'm getting no errors inside the console.
So does someone has an idea file my generated zip file is corrupted ?
This is my code :
OutputStream responseBody = t.getResponseBody();
ByteArrayOutputStream baos = new ByteArrayOutputStream();
ZipOutputStream zos = new ZipOutputStream(baos);
int counter = 1;
for (PDDocument doc : documents)
{
ZipEntry zipEntry = new ZipEntry("document" + counter);
zos.putNextEntry(zipEntry);
ByteArrayOutputStream docOs = new ByteArrayOutputStream();
doc.save(docOs);
docOs.close();
zos.write(docOs.toByteArray());
zos.closeEntry();
zos.finish();
zos.flush();
counter++;
}
zos.close();
baos.close();
responseBody.write(baos.toByteArray());
responseBody.flush();
Thank you for your help !
答案1
得分: 3
你需要从循环内部移除 zos.finish()
,因为它会终止ZIP条目,而这在流的末尾由 zos.close()
处理。
对于非常大的流,最好直接将ZIP发送到 responseBody
,跳过 ByteArrayOutputStream
内存缓冲区。
如果仍然遇到问题,请检查输出的内容类型是否已设置。通过将字节数组暂时写入文件以检查发送的ZIP格式,可能会更容易进行调试:
Files.write(Path.of("temp.zip"), baos.toByteArray());
下面的概述展示了通过HTTP发送简单的ZIP(从Servlet发送,根据需要调整前两行以适应“t”的适当调用)。如果你逐步添加自己的文档对象到循环内部,这可能会帮助你检查代码的哪个步骤导致损坏:
// 必须设置响应内容类型:
// resp.setContentType("application/zip");
OutputStream out = resp.getOutputStream(); // 或 t.getResponseBody();
try (ZipOutputStream zos = new ZipOutputStream(out)) {
while (counter-- > 0) {
ZipEntry zipEntry = new ZipEntry("document" + counter + ".txt");
zos.putNextEntry(zipEntry);
zos.write(("This is ZipEntry: " + zipEntry.getName() + "\r\n").getBytes());
}
}
注意:以上内容为您提供的代码的翻译部分。如有任何疑问,请随时提问。
英文:
You need to remove zos.finish()
from inside the loop as it terminates the ZIP entries, as it is handled by zos.close()
at end of the stream.
With very large streams you will be better off sending ZIP directly to responseBody bypassing ByteArrayOutputStream
memory buffer.
If you are still having problems check the content type of the output is set. It might be easier to debug by temporarily writing the byte[] to file to check the ZIP format you are sending with:
Files.write(Path.of("temp.zip"), baos.toByteArray());
This outline below shows sending a simple ZIP over http (from a servlet, adjust the first 2 lines to appropriate calls for "t"). This may help you check which step of your code causes the corruption if you work back to adding your own document objects inside the loop:
// MUST set response content type:
// resp.setContentType("application/zip");
OutputStream out = resp.getOutputStream(); // or t.getResponseBody();
try(ZipOutputStream zos = new ZipOutputStream(out))
{
while (counter-- > 0)
{
ZipEntry zipEntry = new ZipEntry("document" + counter+".txt");
zos.putNextEntry(zipEntry);
zos.write(("This is ZipEntry: "+zipEntry.getName()+"\r\n").getBytes());
}
}
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论