在文件下载时返回字节数组或servlet输出流之间是否存在差异?

时间:2018-03-01 13:18:33

标签: java spring-mvc download

我想知道Sprin MVC控制器方法返回字节数组byte[]以表示下载文件或将InputStream对象复制到ServletOutputStream时是否存在真正的区别对象

我问的原因是我必须确保在下载大文件时不会出现任何OutOfMemory错误。传递文件是否会通过ServletOutputStream帮助避免它?

传递字节数组:

byte[] download() {
    return getUrlContentAsByteArray();
}

传入ServletOutputStream:

void download(HttpServletResponse response) {
    InputStream content = getUrlContentAsStream();
    ServletOutputStream outputStream = response.getOutputStream();
    response.reset();response.setContentType(ContentType.APPLICATION_OCTET_STREAM.getMimeType());
    IOUtils.copyLarge(inputStream, outputStream);
}

1 个答案:

答案 0 :(得分:3)

在第一个示例中,您必须将整个响应读入内存并将其存储在字节数组中。这将需要至少与响应大小一样多的内存。

在第二个示例中,您不会立即将整个响应保留在内存中,而是使用@RequestMapping(value = "/download", method = RequestMethod.GET) @ResponseBody public ResponseEntity<Resource> download() { HttpHeaders headers = new HttpHeaders(); headers.setContentType(MediaType.APPLICATION_OCTET_STREAM); InputStream is = null; // get your input stream here Resource resource = new InputStreamResource(is); return new ResponseEntity<>(resource, headers, HttpStatus.OK); } 将来自源的多个小块内容复制到servlet响应中。默认情况下,IOUtils使用4kB大缓冲区。但是,您使用的是Spring和Servlet API的奇怪组合。

单独使用Spring MVC,你可以省略servlet API,返回包装为Resource的InputStream,让Spring为你做复制工作:

 var resizeTimer;
    $(window).on('load resize', function () {
        clearTimeout(resizeTimer);
        resizeTimer = setTimeout(function () {
            if ($(window).width() > 768) {
                $('ul.menu-1').show();
                $('.toggle').hide();
            } else {
                $('ul.menu-1').hide();
                $('.toggle').show();
            }
        }, 100);
    });