如何在java中定期刷新ZipOutputStream [英] how to flush the ZipOutputStream periodically in java

查看:47
本文介绍了如何在java中定期刷新ZipOutputStream的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

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

I am trying to archive list of files in zip format and then downloading it for the user on the fly...

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

I am facing out of memory issue when downloading a zip of 1gb size

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

Please help me how i can resolve this without increasing jvm heap size. i would like to flush the stream periodically..

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

I AM TRYING TO FLUSH PERIODICALLY BUT THIS IS NOT WORKING FOR ME.

请在下面找到我的代码:

Please find my code attached below:

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 标头.由于您正在压缩文件,因此您不知道要发送的数据的大小.分块编码允许您以较小的块发送响应片段.不要设置流的内容长度.您可以尝试使用 curl 或其他东西来查看从服务器获得的响应中的 HTTP 标头.如果它没有分块,那么你会想弄清楚.您需要研究如何强制 servlet 容器发送分块编码.您可能需要将其添加到响应头中,以便 servlet 容器将其分块发送.

You want to use chunked encoding to send a file that large otherwise the servlet container will try and figure out the size of the data you are trying to send before sending it so it can set the Content-Length header. Since you are compressing files you don't know the size of the data you're sending. Chunked-Encoding allows you to send pieces of the response in smaller chunks. Don't set the content length of the stream. You might try using curl or something to see the HTTP headers in the response your getting from the server. If it isn't chunked then you'll want to figure that out. You'll want to research how to force the servlet container to send chunked encoding. You might have to add this to the response header to make the servlet container send it chunked.

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

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

The other option would be to compress the file into a temporary file with File.createTemp(), and then send the contents of that. If you compress to a temp file first then you can know how big the file is and set the content length for the servlet.

这篇关于如何在java中定期刷新ZipOutputStream的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆