使用ZipOutputStream损坏的zip文件

问题描述

我正在尝试创建一个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();

谢谢您的帮助!

解决方法

您需要从循环内部删除zos.finish(),因为它会终止ZIP条目,因为它由流末尾的zos.close()处理。

对于非常大的流,最好绕过ByteArrayOutputStream内存缓冲区将ZIP直接发送到responseBody。

如果仍然有问题,请检查输出的内容类型是否已设置。通过将byte []临时写入文件以检查发送的ZIP格式,可能更容易调试:

Files.write(Path.of("temp.zip"),baos.toByteArray());

以下概述显示了通过http发送简单的ZIP(从servlet,将前2行调整为对“ t”的适当调用)。如果您尝试在循环内添加自己的文档对象,这可以帮助您检查代码的哪一步会导致损坏:

// 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());
    }
}