2

我正在使用 commons compress 压缩多个文件并将其从 Servlet 发送到客户端。这些文件可以是任何类型的文件(文本、视频、音频、档案、图像等)的组合。我使用 IOUtils.copy(is, os) 获取文件的 inputStream 并写入 ServletOutputStream。该代码通常适用于任何文档组合,但是当请求下载包含超过 1 个 zip 的文件时,我得到java.io.IOException: Closed 结果,即使 zip 的大小是单个文件大小的总和,创建的 zip 文件也已损坏(我我没有使用压缩)。

我尝试在本地创建 zip 并使用FileOutputStream而不是response.getOutputStream()在构造函数中ZipArchiveOutputStream,它成功了。因此,看起来问题存在于ServletOutputStream.

任何人都可以提出任何解决方法。

这是我的代码:

`try (ZipArchiveOutputStream zos = new ZipArchiveOutputStream( response.getOutputStream())) {
        //get fileList
        for(File file : files) {
           addFileToZip(zos, file.getName(), new BufferedInputStream(new FileInputStream(file)));
        }
        zos.close()
    }

`

public static void addFileToZip(ZipArchiveOutputStream zipOutputStream, String filename, InputStream inputStream) throws FileNotFoundException {
    if(zipOutputStream != null && inputStream != null) {
        try {
            zipOutputStream.putArchiveEntry(new ZipArchiveEntry(filename));
            IOUtils.copy(inputStream, zipOutputStream);
            logger.debug("fileAddedToZip :" + filename);
        } catch (IOException e) {
            logger.error("Error in adding file :" + filename, e); 
        } finally {
            try {
                inputStream.close();
                zipOutputStream.closeArchiveEntry(); //**Starts to fail here after 1st zip is added**
            } catch (IOException e) {
                logger.error("Error in closing zip entry :" + filename, e);
            }
        }
    }
`

这是异常跟踪:`

java.io.IOException: Closed
        at org.mortbay.jetty.AbstractGenerator$Output.write(AbstractGenerator.java:627)
        at org.mortbay.jetty.AbstractGenerator$Output.write(AbstractGenerator.java:577)
        at org.apache.commons.compress.archivers.zip.ZipArchiveOutputStream.writeOut(ZipArchiveOutputStream.java:1287)
        at org.apache.commons.compress.archivers.zip.ZipArchiveOutputStream.writeOut(ZipArchiveOutputStream.java:1272)
        at org.apache.commons.compress.archivers.zip.ZipArchiveOutputStream.writeDataDescriptor(ZipArchiveOutputStream.java:997)
        at org.apache.commons.compress.archivers.zip.ZipArchiveOutputStream.closeArchiveEntry(ZipArchiveOutputStream.java:461)
        at xxx.yyy.zzz.util.ZipUtils.addFileToZip(ZipUtils.java:110)

第 110 行是zipOutputStream.closeArchiveEntry(); //**Starts to fail here after 1st zip is added**

提前致谢。

4

1 回答 1

0

问题是您使用try-with-resources它会自动关闭您在其中创建的流,但您也手动关闭它,因此当 JVM 尝试自动关闭它时,您会遇到java.io.IOException: Closed异常,因为它已经关闭。

如果使用try-with-resources,则无需关闭在其中创建的流。删除您的手动zos.close()声明:

try (ZipArchiveOutputStream zos =
         new ZipArchiveOutputStream(response.getOutputStream())) {

    //get fileList
    for(File file : files) {
       addFileToZip(zos, attachment.getFileName(), is);
    }
} // Here zos will be closed automatically!

另请注意,一旦zos关闭,它也会关闭 servlet 的底层OutputStream,因此您将无法添加更多条目。您必须在关闭之前添加所有内容。

于 2014-09-08T08:20:44.057 回答