通过 Chrome 浏览器从 ServletOutputStream 创建和传递的 zip 文件出现问题

Problems with zip file created and passed from ServletOutputStream via Chrome browser

我设置了一种方法,从我们的 S3 存储桶中输入多个数据文件,试图将它们压缩在一起,然后将它们传递给通过浏览器查询的用户。但是,我无法打开发回的文件。

我已经用 FileOutputStream 进行了测试,并且 zip 文件以正确的格式存储在那里,所以看起来拉、压缩和写入的过程正在运行。

我假设通过 ServletOutputStream 将其传回时存在问题,ServletOutputStream 是使用您在下面看到的 getResponse().getOutputStream() 提取的。然后我在上面调用了 write 方法,这个过程似乎对程序其他部分的 byte[] 格式的单个文件工作正常,只是这里没有。

另一块拼图,我输出的 zip 格式文件和通过 FileOutputStream 工作的文件与通过浏览器和 ServletOutputStream 传送的文件大小相同,所以我认为数据正在结束。相反,虽然我只是得到一个(错误 79 - 不合适的文件类型或格式。)

接受任何建议或帮助!!

File file;

ByteArrayOutputStream byteArrayOutputStream = new ByteArrayOutputStream();
ZipOutputStream zos = new ZipOutputStream(byteArrayOutputStream);

for (String fileName : fileList) {
    key = fileName.replaceAll("=", "%3D");
    file = s3Client.get(bucket, key, Paths.get("/tmp/" + fileName));
    FileInputStream fis = new FileInputStream(file);

    ZipEntry zipEntry = new ZipEntry(fileName);
    zos.putNextEntry(zipEntry);

    //Buffer used to read input stream
    byte[] buffer = new byte[4096];
    int length;
    while ((length = fis.read(buffer)) != -1) {
    //Read input stream to buffer and write this to zip output stream
        zos.write(buffer, 0, length);
    }
    zos.closeEntry();
    fis.close();
}
zos.flush();

getResponse().setContentType("application/zip");
getResponse().setContentLength(byteArrayOutputStream.size());
getResponse().setHeader("Content-Disposition", "attachment; filename=\"" + "test" + "." + "zip" + "\"");
getResponse().setHeader("Connection", "keep-alive");
getResponse().setHeader("Cache-Control", "private");
getResponse().setHeader("Pragma", "private");
getResponse().setDateHeader("Expires", System.currentTimeMillis() + 300000);
getResponse().getOutputStream().write(byteArrayOutputStream.toByteArray());
getResponse().getOutputStream().flush();
zos.close();
byteArrayOutputStream.close();

您没有正确关闭 ZipOutputStream - 对 zos.close(); 的调用必须发生在写入字节之前,而不是之后。

如果使用 try with resources 块和 Files.copy:

,您可以获得更整洁的输出处理
ByteArrayOutputStream byteArrayOutputStream = new ByteArrayOutputStream();
try(ZipOutputStream zos = new ZipOutputStream(byteArrayOutputStream)) {
    for (String fileName : fileList) {
        key = fileName.replaceAll("=", "%3D");
        Path file = s3Client.get(bucket, key, Paths.get("/tmp/" + fileName)).toPath();

        ZipEntry zipEntry = new ZipEntry(fileName);
        zos.putNextEntry(zipEntry);

        Files.copy(file, zos);
    }
};

getResponse().setContentType("application/zip");
getResponse().setContentLength(byteArrayOutputStream.size());
getResponse().setHeader("Content-Disposition", "attachment; filename=\"" + "test" + "." + "zip" + "\"");
getResponse().setHeader("Connection", "keep-alive");
getResponse().setHeader("Cache-Control", "private");
getResponse().setHeader("Pragma", "private");
getResponse().setDateHeader("Expires", System.currentTimeMillis() + 300000);
getResponse().getOutputStream().write(byteArrayOutputStream.toByteArray());
getResponse().getOutputStream().flush();