Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Is there a difference between returning byte array or servlet output stream on file download

I'm wondering if there a real difference when a Sprin MVC controller method returns byte array byte[] to represent a downloaded file or when I copy InputStream object to the ServletOutputStream object?

The reason I'm asking is that I have to make sure that there won't be any OutOfMemory errors when downloading large files. Will the passing file through the ServletOutputStream help to avoid it?

Passing byte array:

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

Passing in the 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);
}
like image 858
androberz Avatar asked Mar 01 '18 13:03

androberz


1 Answers

In your first example, you have to read the entire response into memory and store it in a byte array. That will require at least as much memory as the size of the response.

In your second example, you do not keep the entire response in memory at once, but use IOUtils.copy to copy the content in multiple, small chunks from the source and into the servlet response. IOUtils is by default using a 4kB large buffer. You are however using a strange mix of both Spring and Servlet APIs.

Using Spring MVC alone, you can leave out the servlet API, return the InputStream wrapped as a Resource and let Spring do the copy job for you:

@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);
}
like image 110
jarnbjo Avatar answered Oct 29 '22 08:10

jarnbjo