I just announced the new Spring Boot 2 material, coming in REST With Spring:

>> CHECK OUT THE COURSE

1. Overview

In this tutorial, we’ll illustrate how to return images and other media using the Spring MVC framework.

We will discuss several approaches, starting from directly manipulating HttpServletResponse than moving to approaches that benefit from Message Conversion, Content Negotiation and Spring’s Resource abstraction. We’ll take a closer look on each of them and discuss their advantages and disadvantages.

2. Using the HttpServletResponse

The most basic approach of the image download is to directly work against a response object and mimic a pure Servlet implementation, and its demonstrated using the following snippet:

@RequestMapping(value = "/image-manual-response", method = RequestMethod.GET)
public void getImageAsByteArray(HttpServletResponse response) throws IOException {
    InputStream in = servletContext.getResourceAsStream("/WEB-INF/images/image-example.jpg");
    response.setContentType(MediaType.IMAGE_JPEG_VALUE);
    IOUtils.copy(in, response.getOutputStream());
}

Issuing the following request will render the image in a browser:

http://localhost:8080/spring-mvc-xml/image-manual-response.jpg

The implementation is fairly straightforward and simple owing to IOUtils from the org.apache.commons.io package. However, the disadvantage of the approach is that its not robust against the potential changes. The mime type is hard-coded and the change of the conversion logic or externalizing the image location requires changes to the code.

The following section discusses a more flexible approach.

3. Using the HttpMessageConverter

The previous section discussed a basic approach that does not take advantage of the Message Conversion and Content Negotiation features of the Spring MVC Framework. To bootstrap these feature we need to:

  • Annotate the controller method with the @ResponseBody annotation
  • Register an appropriate message converter based on the return type of the controller method (ByteArrayHttpMessageConverter for example needed for correct conversion of bytes array to an image file)

3.1. Configuration

For showcasing the configuration of the converters, we will use the built-in ByteArrayHttpMessageConverter that converts a message whenever a method returns the byte[] type.

The ByteArrayHttpMessageConverter is registered by default, but the configuration is analogous for any other built-in or custom converter.

Applying the message converter bean requires registering an appropriate MessageConverter bean inside Spring MVC context and setting up media types that it should handle. You can define it via XML, using <mvc:message-converters> tag.

This tag should be defined inside <mvc:annotation-driven> tag, like in the following example:

<mvc:annotation-driven>
    <mvc:message-converters>
        <bean class="org.springframework.http.converter.ByteArrayHttpMessageConverter">
            <property name="supportedMediaTypes">
                <list>
                    <value>image/jpeg</value>
                    <value>image/png</value>
                </list>
            </property>
        </bean>
    </mvc:message-converters>
</mvc:annotation-driven>

Aforementioned configuration part will register ByteArrayHttpMessageConverter for image/jpeg and image/png response content types. If <mvc:message-converters> tag is not present in the mvc configuration, then the default set of converters will be registered.

Also, you can register the message converter using Java configuration:

@Override
public void configureMessageConverters(List<HttpMessageConverter<?>> converters) {
    converters.add(byteArrayHttpMessageConverter());
}

@Bean
public ByteArrayHttpMessageConverter byteArrayHttpMessageConverter() {
    ByteArrayHttpMessageConverter arrayHttpMessageConverter = new ByteArrayHttpMessageConverter();
    arrayHttpMessageConverter.setSupportedMediaTypes(getSupportedMediaTypes());
    return arrayHttpMessageConverter;
}

private List<MediaType> getSupportedMediaTypes() {
    List<MediaType> list = new ArrayList<MediaType>();
    list.add(MediaType.IMAGE_JPEG);
    list.add(MediaType.IMAGE_PNG);
    list.add(MediaType.APPLICATION_OCTET_STREAM);
    return list;
}

3.2. Implementation

Now we can implement our method that will handle requests for media. As it was mentioned above, you need to mark your controller method with the @ResponseBody annotation and use byte[] as the returning type:

@RequestMapping(value = "/image-byte-array", method = RequestMethod.GET)
public @ResponseBody byte[] getImageAsByteArray() throws IOException {
    InputStream in = servletContext.getResourceAsStream("/WEB-INF/images/image-example.jpg");
    return IOUtils.toByteArray(in);
}

To test the method, issue the following request in your browser:

http://localhost:8080/spring-mvc-xml/image-byte-array.jpg

On the advantage side, the method knows nothing about the HttpServletResponse, the conversion process is highly configurable, ranging from using the available converters to specifying a custom one. The content type of the response does not have to be hard-coded rather it will be negotiated based on the request path suffix .jpg.

The disadvantage of this approach is that you need to explicitly implement the logic for retrieving image from a data source (local file, external storage, etc.) and you don’t have a control over the headers or the status code of the response.

4. Using the ResponseEntity Class

You can return an image as byte[] wrapped in the Response Entity. Spring MVC ResponseEntity enables control not only over the body of the HTTP Response but also the header and the respose status code. Following this approach, you need to define the return type of the method as ResponseEntity<byte[]> and create returning ResponseEntity object in the method body.

@RequestMapping(value = "/image-response-entity", method = RequestMethod.GET)
public ResponseEntity<byte[]> getImageAsResponseEntity() {
    HttpHeaders headers = new HttpHeaders();
    InputStream in = servletContext.getResourceAsStream("/WEB-INF/images/image-example.jpg");
    byte[] media = IOUtils.toByteArray(in);
    headers.setCacheControl(CacheControl.noCache().getHeaderValue());
    
    ResponseEntity<byte[]> responseEntity = new ResponseEntity<>(media, headers, HttpStatus.OK);
    return responseEntity;
}

Using the ResponseEntity allows you to configure a response code for a given request.

Explicitly setting the response code is especially useful in the face of an exceptional event e.g. if the image was not found (FileNotFoundException) or is corrupted (IOException). In these cases all that is needed is setting the response code e.g. new ResponseEntity<>(null, headers, HttpStatus.NOT_FOUND), in an adequate catch block.

In addition, if you need to set some specific headers in your response, this approach is more straightforward than setting headers by means of HttpServletResponse object that is accepted by the method as a parameter. It makes the method signature clear and focused.

5. Returning Image Using the Resource Class

Finally, you can return an image in the form of the Resource object.

The Resource interface is an interface for abstracting access to low-level resources. It is introduced in Spring as more capable replacement for the standard java.net.URL class. It allows an easy access to different types of resources (local files, remote files, classpath resources) without need to write a code that explicitly retrieve them.

To use this approach the return type of the method should be set to Resource and you need to annotate the method with the @ResponseBody annotation.

5.1. Implementation

@ResponseBody
@RequestMapping(value = "/image-resource", method = RequestMethod.GET)
public Resource getImageAsResource() {
   return new ServletContextResource(servletContext, "/WEB-INF/images/image-example.jpg");
}

or, if we want more control over the response headers:

@RequestMapping(value = "/image-resource", method = RequestMethod.GET)
@ResponseBody
public ResponseEntity<Resource> getImageAsResource() {
    HttpHeaders headers = new HttpHeaders();
    Resource resource = 
      new ServletContextResource(servletContext, "/WEB-INF/images/image-example.jpg");
    return new ResponseEntity<>(resource, headers, HttpStatus.OK);
}

Using this approach, you treat images as resources that can be loaded using the ResourceLoader interface implementation. In such case, you abstract from the exact location of your image and ResourceLoader decides where from it is loaded.

It provides a common approach to control the location of images using the configuration, and eliminate the need for writting file loading code.

6. Conclusion

Among the aforementioned approaches, we started from the basic approach, than using the approach that benefits from message conversion feature of the framework. We also discussed how to get the set the response code and response headers without handing the response object directly.

Finally, we added flexibility from the image locations point of view, because where to retrieve an image from, is defined in the configuration that is easier to change on the fly.

The sample code following the tutorial is available at GitHub.

I just announced the new Spring Boot 2 material, coming in REST With Spring:

>> CHECK OUT THE LESSONS

newest oldest most voted
Notify of
dhukas
Guest
dhukas

Unfortunately all your approaches do not support http byte-range requests.
See https://jira.spring.io/browse/SPR-13834 – and please vote for it… 😉

Eugen Paraschiv
Guest

Looks interesting – voted.

Praveen R
Guest
Praveen R

this post is 9 months old just wondering do we have any alternative ways of doing byte-range requests. i am on spring boot and using ResponseEntity and wondering how to stream audio/video.

Grzegorz Piwowarek
Guest
Grzegorz Piwowarek
Praveen R
Guest
Praveen R

i will check it, thanks for the link.

Jagruti Frank
Guest
Jagruti Frank

Hi Baeldung, is there any way to produce text and html both
I used @RequestMapping(value=””, method= RequestMethod.GET, produces = MediaType.TEXT_HTML_VALUE)
but it renders text but not the image

Image comes as
info=”name” +name of app;

info =info + “Dpiv: “;

controller is
@RequestMapping(value=””, method= RequestMethod.GET, produces = MediaType.TEXT_HTML_VALUE)
@ResponseBody
String generateInfowithImage(@RequestParam(“id”) final String guid, @RequestParam(“key”) final String esID);

Appreciate your help

Eugen Paraschiv
Guest

Hey Frank – no, there isn’t. A single request has a single response with a single media type. You’ll have to define to separate requests/responses here.
Cheers,
Eugen.

Jagruti Frank
Guest
Jagruti Frank

Hi Eugen,
Many thanks but is resolved
Refer http://stackoverflow.com/questions/42438611/spring-mvc-image-and-text-to-be-rendered?noredirect=1#comment72024973_42438611

to string helped to render photo on webpage

info=info+ “+ ” Photo: “;