Expand Authors Top

If you have a few years of experience in the Java ecosystem and you’d like to share that with the community, have a look at our Contribution Guidelines.

Expanded Audience – Frontegg – Security (partner)
announcement - icon User management is very complex, when implemented properly. No surprise here.

Not having to roll all of that out manually, but instead integrating a mature, fully-fledged solution - yeah, that makes a lot of sense.
That's basically what Frontegg is - User Management for your application. It's focused on making your app scalable, secure and enjoyable for your users.
From signup to authentication, it supports simple scenarios all the way to complex and custom application logic.

Have a look:

>> Elegant User Management, Tailor-made for B2B SaaS

November Discount Launch 2022 – Top
We’re finally running a Black Friday launch. All Courses are 30% off until the end of this week:

>> GET ACCESS NOW

November Discount Launch 2022 – TEMP TOP (NPI)
We’re finally running a Black Friday launch. All Courses are 30% off until the end of this week:

>> GET ACCESS NOW

1. Overview

Serving static files to the client can be done in a variety of ways, and using a Spring Controller isn't necessarily the best available option.

However, sometimes the controller route is necessary, and that's what we'll focus on in this quick tutorial.

2. Maven Dependencies

First, we'll need to add a dependency to our pom.xml:

<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-web</artifactId>
</dependency>

That's all we need to do here. For version information, head over to Maven Central.

3. Using @ResponseBody

The first straightforward solution is to use the @ResponseBody annotation on a controller method to indicate that the object returned by the method should be marshaled directly to the HTTP response body:

@GetMapping("/get-text")
public @ResponseBody String getText() {
    return "Hello world";
}

This method will just return the string Hello world, instead of returning a view whose name is Hello world, like a more typical MVC application.

With @ResponseBody, we can return pretty much any media type, as long as we have a corresponding HTTP Message converter that can handle and marshal it to the output stream.

4. Using produces for Returning Images

Returning byte arrays allows us to return almost anything, such as images or files:

@GetMapping(value = "/image")
public @ResponseBody byte[] getImage() throws IOException {
    InputStream in = getClass()
      .getResourceAsStream("/com/baeldung/produceimage/image.jpg");
    return IOUtils.toByteArray(in);
}

Since we didn't define that the returned byte array is an image, the client won't be able to handle it as an image. In fact, it's more than likely that the browser will simply display the actual bytes of the image.

To define that the returned byte array corresponds to an image, we can set the produces attribute of the @GetMapping annotation to precisely the MIME type of the returned object:

@GetMapping(
  value = "/get-image-with-media-type",
  produces = MediaType.IMAGE_JPEG_VALUE
)
public @ResponseBody byte[] getImageWithMediaType() throws IOException {
    InputStream in = getClass()
      .getResourceAsStream("/com/baeldung/produceimage/image.jpg");
    return IOUtils.toByteArray(in);
}

Here, produces is set to MediaType.IMAGE_JPEG_VALUE to indicate that the returned object must be handled as a JPEG image.

Now the browser will recognize and properly display the response body as an image.

5. Using produces for Returning Raw Data

The parameter produces can be set to a lot of different values (the complete list can be found here) depending on the type of object we want to return.

If we want to return a raw file, we can simply use APPLICATION_OCTET_STREAM_VALUE:

@GetMapping(
  value = "/get-file",
  produces = MediaType.APPLICATION_OCTET_STREAM_VALUE
)
public @ResponseBody byte[] getFile() throws IOException {
    InputStream in = getClass()
      .getResourceAsStream("/com/baeldung/produceimage/data.txt");
    return IOUtils.toByteArray(in);
}

6. Setting contentType Dynamically

Now we'll illustrate how we can set the content type of the response dynamically. In this case, we can't use the produces parameter because it expects a constant. We'll need to directly set the contentType of the ResponseEntity instead:

@GetMapping("/get-image-dynamic-type")
@ResponseBody
public ResponseEntity<InputStreamResource> getImageDynamicType(@RequestParam("jpg") boolean jpg) {
    MediaType contentType = jpg ? MediaType.IMAGE_JPEG : MediaType.IMAGE_PNG;
    InputStream in = jpg ?
      getClass().getResourceAsStream("/com/baeldung/produceimage/image.jpg") :
      getClass().getResourceAsStream("/com/baeldung/produceimage/image.png");
    return ResponseEntity.ok()
      .contentType(contentType)
      .body(new InputStreamResource(in));
}

We'll set the content type of the returned image depending on a query parameter.

7. Conclusion

In this brief article, we discussed a simple problem, returning images or files from a Spring Controller.

As always, the example code can be found over on Github.

November Discount Launch 2022 – Bottom
We’re finally running a Black Friday launch. All Courses are 30% off until the end of this week:

>> GET ACCESS NOW

Generic footer banner
Comments are closed on this article!