zipoutputstream生成损坏的zip文件

发布于 2025-01-30 12:21:08 字数 1797 浏览 4 评论 0原文

我使用下面的代码生成zip文件并将其返回到前端,当文件很小时性能是正常的。但是,当压缩文件超过1GB时,下载的文件将被结合在一起,减少了压缩文件的数量,并且这种现象并不总是发生,有时下载3.2GB文件再次正常= _ =

期待向所有人听到。

        outputStream = response.getOutputStream();
        ZipOutputStream zipOutStream = null;
        FileInputStream filenputStream = null;
        BufferedInputStream bis = null;
        try {
            zipOutStream = new ZipOutputStream(new BufferedOutputStream(outputStream));
            zipOutStream.setMethod(ZipOutputStream.DEFLATED);
            for (int i = 0; i < files.size(); i++) {
                File file = files.get(i);
                filenputStream = new FileInputStream(file);
                bis = new BufferedInputStream(filenputStream);
                zipOutStream.putNextEntry(new ZipEntry(fileName[i]));
                int len = 0;
                byte[] bs = new byte[40];
                while ((len = bis.read(bs)) != -1) {
                    zipOutStream.write(bs,0,len);
                }
                bis.close();
                filenputStream.close();
                zipOutStream.closeEntry();
            }
        } catch (IOException e) {
            e.printStackTrace();
        }  finally {
            try {
                if(Objects.nonNull(filenputStream)) {
                    filenputStream.close();
                }
                if(Objects.nonNull(bis)) {
                    bis.close();
                }
                if (Objects.nonNull(zipOutStream)) {
                    zipOutStream.flush();
                    zipOutStream.close();
                }
                if (Objects.nonNull(outputStream)) {
                    outputStream.close();
                }
            } catch (IOException e) {
                e.printStackTrace();
            }
        }

I use the code below to generate the zip file and return it to the frontend, The performance is normal when the file is small. However, when the compressed file exceeds 1GB, the downloaded file will be conrrupted, and the number of compressed files is reduced, and this phenomenon does not always occur, sometimes downloading 3.2GB files is normal again =_=

Looking forward to hearing from everyone

        outputStream = response.getOutputStream();
        ZipOutputStream zipOutStream = null;
        FileInputStream filenputStream = null;
        BufferedInputStream bis = null;
        try {
            zipOutStream = new ZipOutputStream(new BufferedOutputStream(outputStream));
            zipOutStream.setMethod(ZipOutputStream.DEFLATED);
            for (int i = 0; i < files.size(); i++) {
                File file = files.get(i);
                filenputStream = new FileInputStream(file);
                bis = new BufferedInputStream(filenputStream);
                zipOutStream.putNextEntry(new ZipEntry(fileName[i]));
                int len = 0;
                byte[] bs = new byte[40];
                while ((len = bis.read(bs)) != -1) {
                    zipOutStream.write(bs,0,len);
                }
                bis.close();
                filenputStream.close();
                zipOutStream.closeEntry();
            }
        } catch (IOException e) {
            e.printStackTrace();
        }  finally {
            try {
                if(Objects.nonNull(filenputStream)) {
                    filenputStream.close();
                }
                if(Objects.nonNull(bis)) {
                    bis.close();
                }
                if (Objects.nonNull(zipOutStream)) {
                    zipOutStream.flush();
                    zipOutStream.close();
                }
                if (Objects.nonNull(outputStream)) {
                    outputStream.close();
                }
            } catch (IOException e) {
                e.printStackTrace();
            }
        }

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(1

满天都是小星星 2025-02-06 12:21:08

代码的潜在问题之一是内存泄漏和流,如果代码运行到任何例外,这些泄漏和流无法正确冲洗和关闭。

有助于减少这些泄漏并确保所有资源正确关闭的一种方法,即使发生例外,也要使用try-nith-in-and-and-resources。

这是如何重写您的代码示例以利用try-with-Resources的示例。

在此示例中,要在独立的IDE环境中进行编译,我将其放在名为testStream的函数中>文件和文件名。因此,这两个参数的验证和内容是偶然的,并且假定这两个参数具有相同数量的条目,并且彼此配对(每个元素0都配对在一起)。由于存在这种奇怪的关系,因此它由名为i的变量链接,以镜像原始的源代码。

    public void testStream( HttpServletResponse response, List<File> files, String[] fileName )
    {
        int i = 0;

        try ( 
                ServletOutputStream outputStream = response.getOutputStream();
                ZipOutputStream zipOutStream = new ZipOutputStream( new BufferedOutputStream( outputStream ) ); 
                ) 
        {
            zipOutStream.setMethod( ZipOutputStream.DEFLATED );
            
            for ( File file : files )
            {
                try (
                        BufferedInputStream bis = new BufferedInputStream(
                                 new FileInputStream( file ) );
                        ) {
                    zipOutStream.putNextEntry( new ZipEntry( fileName[i++] ) );
                    int len = 0;
                    byte[] bs = new byte[4096];
                    while ( (len = bis.read( bs )) != -1 )
                    {
                        zipOutStream.write( bs, 0, len );
                    }

                    // optional since putNextEntry will auto-close open entries:
                    zipOutStream.closeEntry();
                }
            }
        }
        catch ( IOException e )
        {
            e.printStackTrace();
        }
    }

这可以成功编译,应该起作用;但是可能需要其他一些调整以使其通过数据在您的环境中工作。希望它可以消除您可能在关闭流和其他资源方面遇到的问题。

One of the potential issues with your code is with memory leaks and streams that are not properly flushed and closed if the code runs in to any exceptions.

One way to help reduce these leaks and to ensure all resources are properly closed, even when exceptions occur, is to use try-with-resources.

Here is an example of how your code example can be rewritten to utilize try-with-resources.

In this example, to get it to compile in a detached IDE environment, I've put it in a function named testStream since I do not have knowledge as to what contributes to the source of the parameters files and fileName. Therefore, validation and content of these two parameters are left to chance, and it is assumed both have the same number of entries, and are paired with each other (element 0 of each are paired together). Since this odd relationship exists, it's linked by the variable named i to mirror the original source code.

    public void testStream( HttpServletResponse response, List<File> files, String[] fileName )
    {
        int i = 0;

        try ( 
                ServletOutputStream outputStream = response.getOutputStream();
                ZipOutputStream zipOutStream = new ZipOutputStream( new BufferedOutputStream( outputStream ) ); 
                ) 
        {
            zipOutStream.setMethod( ZipOutputStream.DEFLATED );
            
            for ( File file : files )
            {
                try (
                        BufferedInputStream bis = new BufferedInputStream(
                                 new FileInputStream( file ) );
                        ) {
                    zipOutStream.putNextEntry( new ZipEntry( fileName[i++] ) );
                    int len = 0;
                    byte[] bs = new byte[4096];
                    while ( (len = bis.read( bs )) != -1 )
                    {
                        zipOutStream.write( bs, 0, len );
                    }

                    // optional since putNextEntry will auto-close open entries:
                    zipOutStream.closeEntry();
                }
            }
        }
        catch ( IOException e )
        {
            e.printStackTrace();
        }
    }

This compiles successfully and should work; but may need some other adjustments to get it to work in your environment with your data. Hopefully it eliminates issues you may have been having with closing streams and other resources.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文