在文件下载时返回字节数组或servlet输出流之间是否有区别?

我想知道当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); } 

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

在第二个示例中,您不会立即将整个响应保留在内存中,而是使用IOUtils.copy将来自源的多个小块内容复制到servlet响应中。 默认情况下,IOUtils使用4kB大缓冲区。 但是,您使用的是Spring和Servlet API的奇怪组合。

单独使用Spring MVC,您可以省略servlet API,返回包装为Resource的InputStream,让Spring为您执行复制作业:

 @RequestMapping(value = "/download", method = RequestMethod.GET) @ResponseBody public ResponseEntity 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); }