vegemite4me
vegemite4me

Reputation: 6856

Spring MVC - setting the content type of a byte[] @ResponseBody

I am using Spring MVC 3.2.2.RELEASE, and this is my first attempt at using Spring's Java based configuration (@Configuration).

I have a controller that I use to handle certain files. The content of the files is read by my service method MyContentService.getResource(String). At the moment, the content type is always text/html.

How can I config my Spring MVC application so that it correctly sets the type of the content returned? The content type can only be determined at runtime.

My controller at the moment, which incorrectly always sets the type to text/html:

@Controller
public class MyContentController {

    MyContentService contentService;

    @RequestMapping(value = "content/{contentId}")
    @ResponseBody
    public byte[] index(@PathVariable String contentId) {
        return contentService.getResource(contentId);
    }
}

EDIT: The following method works (with PNG and JPEG files), but I am not comfortable with URLConnection determining the content type (e.g. PDF, SWF, etc):

@RequestMapping(value = "content/{contentId}/{filename}.{ext}")
public ResponseEntity<byte[]> index2(@PathVariable String contentId, @PathVariable String filename, @PathVariable String ext, HttpServletRequest request) throws IOException {
    byte[] bytes = contentService.getResource(contentId);

    String mimeType = URLConnection.guessContentTypeFromName(filename + "." + ext);
    if (mimeType != null) {
        final HttpHeaders headers = new HttpHeaders();
        headers.setContentType(MediaType.valueOf(mimeType));
        return new ResponseEntity<byte[]>(bytes, headers, HttpStatus.OK);
    } else {
        logger.warn("Unable to determine the mimeType for " + getRequestedUrl(request));
        return new ResponseEntity<byte[]>(HttpStatus.NOT_FOUND);
    }
}

Upvotes: 0

Views: 8261

Answers (1)

M. Deinum
M. Deinum

Reputation: 124506

Currently you are only returning a byte[] which doesn't hold much information, only the actual content (as a byte[]).

You can wrap the byte[] in a HttpEntity or ResponseEntity and set the appropriate content type on that. Spring MVC will use the content type of the entity to set the actual content type to the response.

To determine the filetype you can use the FileTypeMap of the javax.activation framework or use a library (see Getting A File's Mime Type In Java).

@RequestMapping(value = "content/{contentId}")
@ResponseBody
public HttpEntity index(@PathVariable String contentId) {
    String filepath = // get path to file somehow
    String contentType = FileTypeMap.getDefaultFileTypeMap().getContentType(filePath);
    byte[] content = contentService.getResource(contentId);
    final HttpHeaders headers = new HttpHeaders();
    headers.setContentType(MediaType.valueOf(mimeType));
    return new HttpEntity(content, headers);
}

Upvotes: 2

Related Questions