Download an Image or a File with Spring MVC – 用Spring MVC下载图片或文件

最后修改: 2017年 3月 24日

中文/混合/英文(键盘快捷键:t)

1. Overview

1.概述

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.

向客户端提供静态文件的方式有很多种,使用Spring控制器不一定是最好的可用选项。

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

然而,有时控制器路线是必要的,这就是我们在这个快速教程中要关注的。

2. Maven Dependencies

2.Maven的依赖性

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

首先,我们需要在我们的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.

这就是我们需要做的一切。关于版本信息,请到Maven Central

3. Using @ResponseBody

3.使用@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:

第一个直接的解决方案是在控制器方法上使用@ResponseBody注解,表示该方法返回的对象应该直接被编入HTTP响应体。

@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.

这个方法将只是返回字符串Hello world,,而不是像更典型的MVC应用程序那样,返回一个名称为Hello world的视图。

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.

通过@ResponseBody,我们可以返回几乎所有的媒体类型,只要我们有一个相应的HTTP消息转换器,可以处理并将其编入输出流。

4. Using produces for Returning Images

4.使用生产来返回图像

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注解的produces属性精确设置为返回对象的MIME类型。

@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.

这里,produces被设置为MediaType.IMAGE_JPEG_VALUE,以表明返回的对象必须被处理为JPEG图像。

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

现在,浏览器将识别并正确显示响应体为图像。

5. Using produces for Returning Raw Data

5.使用produces来返回原始数据

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.

参数produces可以被设置为很多不同的值(完整的列表可以在这里找到),取决于我们想要返回的对象的类型。

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

如果我们想返回一个原始文件,我们可以简单地使用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

6.动态设置contentType

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:

现在我们将说明我们如何动态地设置响应的内容类型。在这种情况下,我们不能使用produces参数,因为它期望一个常数。我们需要直接设置ResponseEntitycontentType来代替。

@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

7.结语

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

在这篇简短的文章中,我们讨论了一个简单的问题,从Spring控制器中返回图像或文件。

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

一如既往,示例代码可以在Github上找到over