java - 如何在 java 中定期刷新 ZipOutputStream

标签 java memory zip

我正在尝试以 zip 格式存档文件列表,然后为用户即时下载...

我在下载 1gb 大小的 zip 时遇到内存不足的问题

请帮助我如何在不增加 jvm 堆大小的情况下解决此问题。我想定期刷新流..

我正在尝试定期冲洗,但这对我不起作用。

请在下面找到我的代码:

try{
ServletOutputStream out = response.getOutputStream();
        ZipOutputStream zip = new ZipOutputStream(out);

        response.setContentType("application/octet-stream");
        response.addHeader("Content-Disposition",
                "attachment; filename=\"ResultFiles.zip\"");
                  //adding multiple files to zip
        ZipUtility.addFileToZip("c:\\a", "print1.txt", zip);
ZipUtility.addFileToZip("c:\\a", "print2.txt", zip);
ZipUtility.addFileToZip("c:\\a", "print3.txt", zip);
ZipUtility.addFileToZip("c:\\a", "print4.txt", zip);

zip.flush();        
zip.close();
out.close();
} catch (ZipException ex) {
            System.out.println("zip exception");             
        } catch (Exception ex) {
            System.out.println("exception");
            ex.printStackTrace();   
}

public class ZipUtility {

    static public void addFileToZip(String path, String srcFile,
            ZipOutputStream zip) throws Exception {

        File file = new File(path + "\\" + srcFile);
        boolean exists = file.exists();
        if (exists) {

            long fileSize = file.length();
            int buffersize = (int) fileSize;
            byte[] buf = new byte[buffersize];

            int len;
            FileInputStream fin = new FileInputStream(path + "\\" + srcFile);
            zip.putNextEntry(new ZipEntry(srcFile));
            int bytesread = 0, bytesBuffered = 0;
            while ((bytesread = fin.read(buf)) > -1) {
                zip.write(buf, 0, bytesread);
                bytesBuffered += bytesread;
                if (bytesBuffered > 1024 * 1024) { //flush after 1mb
                    bytesBuffered = 0;
                    zip.flush();

                }
            }
            zip.closeEntry();
            zip.flush();
            fin.close();
        }

    }
}

}

最佳答案

您想使用分块编码来发送这么大的文件,否则 servlet 容器将在发送之前尝试计算出您尝试发送的数据的大小,以便它可以设置 Content-Length header 。由于您正在压缩文件,因此您不知道要发送的数据的大小。 Chunked-Encoding 允许您以较小的 block 发送响应片段。不要设置流的内容长度。您可以尝试使用 curl 或其他工具来查看从服务器获得的响应中的 HTTP header 。如果它没有分块,那么您将需要弄清楚。您需要研究如何强制 servlet 容器发送分块编码。您可能必须将此添加到响应 header ,以使 servlet 容器将其分块发送。

response.setHeader("Transfer-Encoding", "chunked");

另一种选择是使用 File.createTemp() 将文件压缩到一个临时文件中,然后发送其中的内容。如果您先压缩到一个临时文件,那么您可以知道该文件有多大并为 servlet 设置内容长度。

关于java - 如何在 java 中定期刷新 ZipOutputStream,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/7108035/

相关文章:

c# - 工具条内存泄漏

Golang 从内存中的二进制数据执行子进程

java - 刷新前修改实体

java - 如何使用 Java 替换目录中的多个 HTML 标题?

gcc - LDMIA 指令在皮质 M4 的外部 SRAM 上无法正常工作

python - shutil make_archive 生成​​嵌套的 .zip 文件

java - 将本地目录中的 zip 文件放入 java spring boot 中的列表中

python - 比较 Pandas 系列中的前一个值和下一个值

java - Spring Boot @Before 插入数据不可用

java - 如何将文本文件放入Java中的哈希表中?