Java下载文件使用通道流最多2G解决办法

今天分享一个我在一个客户现场碰到的问题。

因为客户那边的文件都比较大,在现场他们从服务器提取文件的流程又很麻烦,并且不允许使用ftp这种形式。所以只能通过流的形式慢慢往出读取。从一开始就碰到了问题,前端会报 

504 Gateway Time-out 

针对这一个问题,我们只能通过调整请求响应时间的方式。因为是持续通过流的形式往response写,很耗费时间,文件很大的话就会超时。刚好我们的前端是通过nginx部署,解决方案很多,修改几个配置即可

改完配置接着测试,传统的通过通道流下载方法如下:

private void downloadLargeFile(final File file, final String resultFileName, final HttpServletResponse response) {
    OutputStream os = null;
    try {
        response.reset();
        response.setContentType("application/x-msdownload");
        response.setHeader("Content-disposition", "attachment; filename=" + (StringUtils.isBlank(resultFileName) ? file.getName() : resultFileName));
        os = response.getOutputStream();
        final String path = Files.probeContentType(Paths.get(file.getAbsolutePath()));
        log.info("path的值为------------------" + path);
        final FileInputStream in = new FileInputStream(file);
        final WritableByteChannel writableByteChannel = Channels.newChannel(os);
        final FileChannel fileChannel = in.getChannel();
        fileChannel.transferTo(0, fileChannel.size(), writableByteChannel);
        fileChannel.close();
        os.flush();
    } catch (final IOException e) {
        e.printStackTrace();
    } finally {
        if (os != null) {
            try {
                os.close();
            } catch (final IOException e) {
                e.printStackTrace();
            }
        }
    }
}

这总方式比普通流要速度更快,但是FileChannel.transferTo()方法对于2G以上的文件也只有2G

解决方法也很简单,只需要把下载方法改造一下(把fileChannel.transferTo方法替换为下述代码)

            //文件大小
            long size = fileChannel.size();
            //偏移量
            long position = 0;
            while (position < fileChannel.size()) {
                //通道最多进入2048MB
                long count = fileChannel.transferTo(position,size,writableByteChannel);
                if (count>0) {
                    position+=count;
                    size-=count;
                }
            }
            //fileChannel.transferTo(0, fileChannel.size(), writableByteChannel);

这样就可以解决2G的限制了。但也不是多大就可以,受到请求时间的限制,以及客户端临时文件空间限制(因为在客户端下载的时候,客户端浏览器首先会把response流写入本地硬盘上的临时文件中),经过我的电脑测试,10G左右的文件还是可以下载的。

Java下载文件使用通道流最多2G解决办法_第1张图片

你可能感兴趣的:(java,nginx,linux)