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

Posted

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了在文件下载时返回字节数组或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<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输出流之间是否存在差异?的主要内容,如果未能解决你的问题,请参考以下文章

servlet中文乱码问题

Java文件 ---流

字节流 字符流 输入流 输出流

字节流 字符流 输入流 输出流

如何将base64位的字节数组转换成图片并显示

《七》随机访问文件流