Skip to main content

Spring 响应图片等媒体数据

· 3 min read
Alan

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.ioIOUtils 非常简单直接, 缺点是这种方式对于潜在的改变缺少鲁棒性. 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);
}