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

and*_*erz 5 java spring-mvc download

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

我要问的原因是我必须确保下载大文件时不会出现OutOfMemory错误。将通过ServletOutputStream帮助的传递文件避免了吗?

传递字节数组:

byte[] download() {
    return getUrlContentAsByteArray();
}
Run Code Online (Sandbox Code Playgroud)

传递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);
}
Run Code Online (Sandbox Code Playgroud)

jar*_*bjo 5

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

在您的第二个示例中,您不会立即将整个响应保存在内存中,而是用于IOUtils.copy将内容以多个小块的形式从源复制到 servlet 响应中。IOUtils 默认使用 4kB 大缓冲区。然而,您正在使用 Spring 和 Servlet API 的奇怪组合。

单独使用 Spring MVC,您可以省去 servlet API,返回包装为 Resource 的 InputStream 并让 Spring 为您完成复制工作:

@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);
}
Run Code Online (Sandbox Code Playgroud)