5

I have a controller method that simply streams bytes for media (images, css, js, etc.) to the client. I first tried something like this:

@RequestMapping(value="/path/to/media/**", method=RequestMethod.GET)
@ResponseBody
public byte[] getMedia(HttpServletRequest request) throws IOException
{
    //logic for getting path to media on server

    return Files.readAllBytes(Paths.get(serverPathToMedia));
}

I originally tested this in Firefox, and it all seemed to work fine. However, I then tried it in Chrome, and then found that none of the images work. So, I then changed it to something like this:

@RequestMapping(value="/path/to/media/**", method=RequestMethod.GET)
public ResponseEntity<byte[]> getMedia(HttpServletRequest request) throws IOException
{
    //logic for getting path to media on server

    byte[] bytes = Files.readAllBytes(Paths.get(serverPathToMedia));
    //logic for setting some header values like Content-Type and Content-Length
    return new ResponseEntity<byte[]>(bytes, headers, HttpStatus.OK);
}

This gave the same results as before. I saw in the developer tools that my response headers were coming down as expected, but still no image bytes

Next I tried something like this:

@RequestMapping(value="/path/to/media/**", method=RequestMethod.GET)
public void getMedia(HttpServletRequest request, HttpServletResponse response) throws IOException
{
    //logic for getting path to media on server

    byte[] bytes = Files.readAllBytes(Paths.get(serverPathToMedia));
    response.getOutputStream().write(bytes);
}

Without even setting any response headers, this works in Firefox and Chrome. Now, while I can just do it this last way since it works, this doesn't seem like the correct Spring MVC way. I want to know why the first two things I tried didn't work, as they seem more correct. Also, is there something I didn't try that would actually be the right way to do this?

dnc253
  • 39,967
  • 41
  • 141
  • 157

1 Answers1

5

Your last approach is pretty much the way to go about it. The only change that I can suggest is to not keep the entire content file to be streamed in memory, instead to stream out the content with buffering - IOUtils from Apache commons can do this for you.

Biju Kunjummen
  • 49,138
  • 14
  • 112
  • 125
  • 1
    can you give an example why mvc resources won't work here? I don't think that css and js files need some special handling. – Boris Treukhov Dec 22 '12 at 20:53
  • Oh yes, I thought for some reason that the objective was to stream out application specific files, not content like js, img, from specific locations, like I have realized now. Do add it as an answer and I will +1 it :-) – Biju Kunjummen Dec 22 '12 at 20:58
  • I'd really rather not have the response as a parameter into this controller method. If I have to, I have to, but why don't the first two approaches work? – dnc253 Dec 22 '12 at 21:47
  • The problem with the first two approaches is that they hold the entire file content in memory. Assuming that is okay for you, the response type is further acted on by a HttpMessageConverter to marshal custom types based on the original Accept header from the client - not completely sure how the `byte[]` response would be handled for the for you. If the static resources are at a fixed location, can you try using `` like Boris has suggested. – Biju Kunjummen Dec 23 '12 at 13:41
  • I briefly looked into the HttpMessageConverter stuff, and I'd rather just write straight to the response than having to mess with all that. Thank you to both you and @BorisTreukhov for the help. – dnc253 Jan 09 '13 at 05:04