via Returning Image/Media Data with Spring MVC
本文讨论如何使用 Spring MVC 框架返回图片或者其他媒体数据.
使用 HttpServletResponse
实现图片下载, 最基本的方式是通过 response
对象:
import org.apache.commons.io.IOUtils;
import org.springframework.http.MediaType;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import java.io.InputStream;
import java.nio.file.Files;
import java.nio.file.Paths;
import javax.servlet.http.HttpServletResponse;
@RequestMapping(value = "/image", method = RequestMethod.GET)
public void image1(HttpServletResponse response) throws Exception {
InputStream in = Files.newInputStream(Paths.get("/Users/alan/workspace/temporary/test.png"));
response.setContentType(MediaType.IMAGE_PNG_VALUE);
IOUtils.copy(in, response.getOutputStream());
}
然后使用浏览器访问 http://localhost:8080/spring-mvc-xml/image-manual-response.jpg 下载.
上面的实现, 利用 org.apache.commons.io 的 IOUtils
非常简单直接, 缺点是这种方式对于潜在的改变缺少鲁棒性. mime类型也是硬编码.
下面讨论更加弹性的方式.
使用 HttpMessageConverter
本地没跑通, 忽略
下面利用 Spring MVC 框架的 消息转换 和 内容协商 特性:
- 在controller的方法上使用
@ResponseBody
注解 - 基于controller方法的返回类型, 注册合适的消息转换器(
ByteArrayHttpMessageConverter
)
配置
为了演示转换器的配置, 我们使用内置的 ByteArrayHttpMessageConverter
, 该转换器转换方法返回的 byte[]
类型.
框架默认注册了ByteArrayHttpMessageConverter
, 配置和其他内置转换器一样.
下面通过Java配置方式注册消息转换器:
AppConfig.java
package com.alanwei.net.demo.config;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.http.MediaType;
import org.springframework.http.converter.ByteArrayHttpMessageConverter;
import org.springframework.http.converter.HttpMessageConverter;
import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;
import java.util.Arrays;
import java.util.List;
@Configuration
public class AppConfig implements WebMvcConfigurer {
@Override
public void configureMessageConverters(List<HttpMessageConverter<?>> converters) {
converters.add(this.byteArrayHttpMessageConverter());
}
@Bean
public ByteArrayHttpMessageConverter byteArrayHttpMessageConverter(){
ByteArrayHttpMessageConverter converter = new ByteArrayHttpMessageConverter();
converter.setSupportedMediaTypes(Arrays.asList(MediaType.IMAGE_JPEG, MediaType.IMAGE_PNG));
return converter;
}
}
控制器方法如下:
@RequestMapping(value = "/image2", method = RequestMethod.GET)
public @ResponseBody byte[] image2() throws Exception {
InputStream in = Files.newInputStream(Paths.get("/Users/alan/workspace/temporary/test.png"));
return IOUtils.toByteArray(in);
}
使用 ResponseEntity
类
控制器方法可以返回ResponseEntity<byte[]>
类型的数据. Spring MVC 的 ResponseEntity
类不仅能控制响应体内容, 还能控制状态码和响应头:
@RequestMapping(value = "/image3", method = RequestMethod.GET)
public ResponseEntity<byte[]> image3() throws Exception {
byte[] data = Files.readAllBytes(Paths.get("/Users/alan/workspace/temporary/test.png"));
HttpHeaders headers = new HttpHeaders();
headers.setContentType(MediaType.IMAGE_PNG);
return new ResponseEntity<>(data, headers, HttpStatus.OK);
}