将压缩目录输出到 ByteArrayOutputStream

use*_*356 1 java file-io servlets

我有一个用这种方法压缩的目录:

 public byte[] archiveDir(File dir)  {
    try(ByteArrayOutputStream bos = new ByteArrayOutputStream(); ZipOutputStream zout = new ZipOutputStream(bos)) {
        zipSubDirectory("", dir, zout);
        return bos.toByteArray();
    } catch (IOException e) {
        throw new RuntimeException(e);
    }
}

private void zipSubDirectory(String basePath, File dir, ZipOutputStream zout) throws IOException {
    byte[] buffer = new byte[4096];
    File[] files = dir.listFiles();
    for (File file : files) {
        if (file.isDirectory()) {
            String path = basePath + file.getName() + "/";
            zout.putNextEntry(new ZipEntry(path));
            zipSubDirectory(path, file, zout);
            zout.closeEntry();
        } else {
            FileInputStream fin = new FileInputStream(file);
            zout.putNextEntry(new ZipEntry(basePath + file.getName()));
            int length;
            while ((length = fin.read(buffer)) > 0) {
                zout.write(buffer, 0, length);
            }
            zout.closeEntry();
            fin.close();
        }
    }
}
Run Code Online (Sandbox Code Playgroud)

然后我将字节写入 servlet 的输出流。但是当我收到 zip 文件时,它无法打开“文件格式错误”。如果我将压缩的内容输出到 FileOutputStream,然后将文件内容发送到 servlet 的输出流,它就可以正常工作。好吧,这将解决我的问题,但在这种情况下,在将临时 zip 文件的内容发送到 servlet 的输出流后,我总是必须删除它。是否可以仅在内存中执行此操作。

Joo*_*gen 5

唔,

        zipSubDirectory(path, file, zout);
        zout.closeEntry();
Run Code Online (Sandbox Code Playgroud)

应该:

        zout.closeEntry();
        zipSubDirectory(path, file, zout);
Run Code Online (Sandbox Code Playgroud)

主要错误似乎是在调用 toByteArray之前没有关闭/刷新 zout 。这里的 try-with-resources 有点狡猾。

try (ByteArrayOutputStream bos = new ByteArrayOutputStream()) {
    try ((ZipOutputStream zout = new ZipOutputStream(bos)) {
        zipSubDirectory("", dir, zout);
    }
    return bos.toByteArray();
} catch (IOException e) {
    throw new RuntimeException(e);
}
Run Code Online (Sandbox Code Playgroud)