【问题标题】:Write multiple Zip files to an OutputStream using IOUtils.copy method使用 IOUtils.copy 方法将多个 Zip 文件写入 OutputStream
【发布时间】:2022-01-20 07:30:58
【问题描述】:

这个问题我觉得很难解释,但我尽力了。

目前,我有一个方法可以返回一个带有 Zip 文件的 InputStream,我必须将其添加到主 zip 文件中。问题是当我在OutputStream 中写入内容时,它会覆盖以前写入的数据。我尝试使用ZipOutputStreamZipEntries 但这会重新压缩文件并做一些奇怪的事情,所以它不是一个解决方案。我必须使用且不可协商的东西是:

  • 使用返回 InputStream 的方法检索文件

  • 使用IOUtils.copy() 方法下载文件(如果您有其他解决方案允许我通过浏览器下载文件,这可能是可选的)

这是目前为止的代码:

OutputStream os = null;
InputStream is = null;      
        
try {
    os = response.getOutputStream();
    for (int i = 0; i < splited.length; i += 6) {
        String[] file= //an array with the data to retrieve the file
        is = FileManager.downloadFile(args);
                    
        int read;
        byte[] buffer = new byte[1024];
        while (0 < (read = is.read(buffer))) {
                        
            os.write(buffer, 0, read);
        }
    }
} catch (Exception ex) {
    //Exception captures
} 

response.setHeader("Content-Disposition", "attachment; filename=FileName");
response.setContentType("application/zip");

        
IOUtils.copy(is, os);

os.close();
is.close();
        
return forward;

【问题讨论】:

  • 您的循环已经将整个数据从is 复制到os,那么在复制完所有内容后调用IOUtils.copy(is, os); 有什么意义呢?而且你明白你的代码只会关闭最后一个InputStream吗?

标签: java file download java-stream zip


【解决方案1】:

您可以使用 ZipOutputStream 包装响应的 OutputStream,而不是 close 调用完成,并且不要在 ResponseOutputStream 上调用 close。

您必须从 HTTP 标头开始。

response.setHeader("Content-Disposition", "attachment; filename=FileName");
response.setContentType("application/zip");
try {
    ZipOutputStream os = new ZipOutputStream(response.getOutputStream());
    for (int i = 0; i < splited.length - 5; i += 6) {
        String[] file= //an array with the data to retrieve the file
        try (InputStream is = FileManager.downloadFile(args)) {               
            os.putNextEntry(new ZipEntry(filePath));
            is.TransferTo(os);
            os.closeEntry();
        }
    }
    os.finish();
} catch (Exception ex) {
    //Exception captures
} 
return forward;

由于 java 9 transferTo 复制输入/输出流。 也可以使用Files.copy(Path, OutputStream) 复制Path,其中PathFile 的基于URI 的泛化,因此也可以立即复制URL。

这里 try-with-resources 确保每个 is 都被关闭。

【讨论】:

  • 不能使用 transferTo 方法,因为我使用的是 Java 8
  • 这解释了缓冲的复制代码。 Apache 的 IOUtils 也有复制功能,(只要确保 - 使用时 - 它不会关闭输出)。
猜你喜欢
  • 2011-12-23
  • 1970-01-01
  • 1970-01-01
  • 2013-03-15
  • 2021-01-15
  • 1970-01-01
  • 2011-02-14
  • 2011-06-18
  • 1970-01-01
相关资源
最近更新 更多