将包含多个文件的Inputstream放入一个ZipEntry中

时间:2019-04-10 08:20:09

标签: java inputstream zipoutputstream

我想将File的数组压缩为一个zipfile并将其发送到浏览器。每个Inputstream的{​​{1}}是一个shapefile,实际上包含多个文件(.shp,.dbf,.shx等)。

当我仅发送一个带有以下代码的File时,它可以正常工作,并返回一个zipfile,其中包含所有需要的文件。

发送单个文件的代码

File

当我尝试将所有文​​件一起发送时,将返回一个zipfile,其中包含所需的文件夹,但是在每个文件夹中,仅存在一个带有.file扩展名的元素。与FileInputStream is = new FileInputStream(files.get(0)); response.setContentType("application/octet-stream"); response.setHeader("Content-Disposition", "attachment; filename=" + getCurrentUser(request).getNiscode() + ".zip"); while (is.available() > 0) { response.getOutputStream().write(is.read()); } is.close(); if (response.getOutputStream() != null) { response.getOutputStream().flush(); response.getOutputStream().close(); } 的条目有关吗?

发送所有文件的代码

ZipOutputStream
byte[] zip = this.zipFiles(files, Ids);

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

response.getOutputStream().write(zip);
response.flushBuffer();

3 个答案:

答案 0 :(得分:2)

根据您的代码,看来files数组中的每个文件已经是一个zip文件

稍后再执行zipFiles时,您正在制作的zip文件在其文件夹中包含更多的zip文件。您显然不希望这样做,但是您想要一个包含文件夹的zip文件,其中包含所有可能的zip文件的内容。

基于现有的Thanador位于“ Reading data from multiple zip files and combining them to one”的答案,我设计了以下解决方案,其中还包括目录和适当的流处理:

/**
 * Combine multiple zipfiles together
 * @param files List of file objects pointing to zipfiles
 * @param ids List of file names to use in the final output
 * @return The byte[] object representing the final output
 * @throws IOException When there was a problem reading a zipfile
 * @throws NullPointerException When there either input is or contains a null value
 */
private byte[] zipFiles(ArrayList<File> files, String[] ids) throws IOException {
    ByteArrayOutputStream baos = new ByteArrayOutputStream();

    // Buffer to copy multiple bytes at once, this is generally faster that just reading and writing 1 byte at a time like your previous code does
    byte[] buf = new byte[16 * 1024];
    int length = files.size();
    assert length == ids.length;
    try (ZipOutputStream zos = new ZipOutputStream(baos)) {
        for (int i = 0; i < length; i++) {
            try (ZipInputStream inStream = new ZipInputStream(new FileInputStream(files.get(i))) {
                ZipEntry entry;
                while ((entry = inStream.getNextEntry()) != null) {
                    zos.putNextEntry(new ZipEntry(ids[i] + "/" + entry.getName()));
                    int readLength;
                    while ((readLength = inStream.read(buf)) > 0) {
                        zos.write(buf, 0, readLength);
                    }
                }
            }
        }
    }

    return baos.toByteArray();
}
  • 从技术上讲,它可以更快,更高效地直接写入您从response.getOutputStream()获得的输出流,但是在上例中我没有这样做,因此您可以轻松地在您的代码
  • 如果关闭流,它将自动刷新它,我正在使用try-with-resources关闭它们

答案 1 :(得分:0)

尝试以下解决方案:

private byte[] zipFiles(ArrayList<File> files, String[] Ids) throws IOException {
        ByteArrayOutputStream baos = new ByteArrayOutputStream();
        ZipOutputStream zos = new ZipOutputStream(baos);
    for (File file : files) {
        ZipEntry ze= new ZipEntry(file.getName());
        zos.putNextEntry(ze);

        FileInputStream fis = new FileInputStream(file);

        int len;
        while ((len = fis .read(buffer)) > 0) {
            zos.write(buffer, 0, len);
        }

        fis .close();
    }
    byte[] byteArray = baos.toByteArray();
    zos.flush();
    baos.flush();
    zos.close();
    baos.close();

    return byteArray;
}

IDK为什么要放置count变量以及为什么要放置两次zos.putNextEntry(new ZipEntry())

答案 2 :(得分:0)

 public static void compressListFiles(List<Pair<String, String>> filePairList, ZipOutputStream zipOut) throws Exception {
    for (Pair<String, String> pair : filePairList) {
        File fileToZip = new File(pair.getValue());
        String fileId = pair.getKey();
        FileInputStream fis = new FileInputStream(fileToZip);
        ZipEntry zipEntry = new ZipEntry(fileId + "/" + fileToZip.getName());
        zipOut.putNextEntry(zipEntry);
        byte[] bytes = new byte[1024];
        int length;
        while ((length = fis.read(bytes)) >= 0) {
            zipOut.write(bytes, 0, length);
        }
        fis.close();
    }
}