Spring MVC:如何在@ResponseBody中返回图像?

我从数据库中获取图像数据(如byte[] )。 如何在@ResponseBody返回这个图片?

编辑

我没有使用@ResponseBody使用HttpServletResponse作为方法参数:

 @RequestMapping("/photo1") public void photo(HttpServletResponse response) throws IOException { response.setContentType("image/jpeg"); InputStream in = servletContext.getResourceAsStream("http://img.dovov.comno_image.jpg"); IOUtils.copy(in, response.getOutputStream()); } 

使用@ResponseBody与注册org.springframework.http.converter.ByteArrayHttpMessageConverter转换器@Sid说不适用于我:(。

 @ResponseBody @RequestMapping("/photo2") public byte[] testphoto() throws IOException { InputStream in = servletContext.getResourceAsStream("http://img.dovov.comno_image.jpg"); return IOUtils.toByteArray(in); } 

如果您使用的是3.1或更新版本的Spring版本,则可以在@RequestMapping注释中指定“产生”。 下面的例子为我开箱即用。 如果您启用了web mvc( @EnableWebMvc ),则无需注册转换器或其他任何东西。

 @ResponseBody @RequestMapping(value = "/photo2", method = RequestMethod.GET, produces = MediaType.IMAGE_JPEG_VALUE) public byte[] testphoto() throws IOException { InputStream in = servletContext.getResourceAsStream("http://img.dovov.comno_image.jpg"); return IOUtils.toByteArray(in); } 

使用Spring 4.1及以上版本,您可以非常简单地返回任何东西(如图片,pdf,文档,jar子,拉链等),而无需任何额外的依赖关系。 例如,以下可能是从MongoDB GridFS返回用户个人资料图片的方法:

 @RequestMapping(value = "user/avatar/{userId}", method = RequestMethod.GET) @ResponseBody public ResponseEntity<InputStreamResource> downloadUserAvatarImage(@PathVariable Long userId) { GridFSDBFile gridFsFile = fileService.findUserAccountAvatarById(userId); return ResponseEntity.ok() .contentLength(gridFsFile.getLength()) .contentType(MediaType.parseMediaType(gridFsFile.getContentType())) .body(new InputStreamResource(gridFsFile.getInputStream())); } 

要注意的是:

  • 用InputStreamResource作为返回types的ResponseEntity

  • ResponseEntity构build器样式创build

有了这个方法,你不必担心HttpServletResponse中的自动assembly,抛出一个IOException或者复制stream数据。

除了注册ByteArrayHttpMessageConverter ,您可能还想使用ResponseEntity而不是@ResponseBody 。 以下代码适用于我:

 @RequestMapping("/photo2") public ResponseEntity<byte[]> testphoto() throws IOException { InputStream in = servletContext.getResourceAsStream("http://img.dovov.comno_image.jpg"); final HttpHeaders headers = new HttpHeaders(); headers.setContentType(MediaType.IMAGE_PNG); return new ResponseEntity<byte[]>(IOUtils.toByteArray(in), headers, HttpStatus.CREATED); } 

通过使用Spring 3.1.x和3.2.x,这是你应该这样做的:

控制器方法:

 @RequestMapping("/photo2") public @ResponseBody byte[] testphoto() throws IOException { InputStream in = servletContext.getResourceAsStream("http://img.dovov.comno_image.jpg"); return IOUtils.toByteArray(in); } 

和servlet-context.xml文件中的mvc注释:

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

除了几个答案之外(Spring 4.1)。

如果您没有在WebMvcConfig中configuration任何消息转换器,那么在您的@ResponseBody中有ResponseEntity可以@ResponseBody工作。

如果你这样做,即你有一个MappingJackson2HttpMessageConverterconfiguration(像我一样)使用ResponseEntity返回一个org.springframework.http.converter.HttpMessageNotWritableException

在这种情况下唯一的工作解决scheme是在@ResponseBody包装一个byte[] ,如下所示:

 @RequestMapping(value = "/get/image/{id}", method=RequestMethod.GET, produces = MediaType.IMAGE_PNG_VALUE) public @ResponseBody byte[] showImageOnId(@PathVariable("id") String id) { byte[] b = whatEverMethodUsedToObtainBytes(id); return b; } 

在这种情况下,请记住在WebMvcConfig中正确configurationmessageconverters(并添加一个ByteArrayHttpMessageConverer ),如下所示:

 @Override public void configureMessageConverters(List<HttpMessageConverter<?>> converters) { converters.add(mappingJackson2HttpMessageConverter()); converters.add(byteArrayHttpMessageConverter()); } @Bean public MappingJackson2HttpMessageConverter mappingJackson2HttpMessageConverter() { ObjectMapper objectMapper = new ObjectMapper(); objectMapper.disable(SerializationFeature.WRITE_DATES_AS_TIMESTAMPS); objectMapper.setSerializationInclusion(JsonInclude.Include.NON_NULL); MappingJackson2HttpMessageConverter converter = new MappingJackson2HttpMessageConverter(); converter.setObjectMapper(objectMapper); return converter; } @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; } 

在您的应用程序上下文中声明一个AnnotationMethodHandlerAdapter和registerByteArrayHttpMessageConverter:

 <bean class="org.springframework.web.servlet.mvc.annotation.AnnotationMethodHandlerAdapter"> <property name="messageConverters"> <util:list> <bean id="byteArrayMessageConverter" class="org.springframework.http.converter.ByteArrayHttpMessageConverter"/> </util:list> </property> </bean> 

也在处理程序方法中为你的响应设置适当的内容types。

  @RequestMapping(value = "/get-image",method = RequestMethod.GET) public ResponseEntity<byte[]> getImage() throws IOException { RandomAccessFile f = new RandomAccessFile("/home/vivex/apache-tomcat-7.0.59/tmpFiles/1.jpg", "r"); byte[] b = new byte[(int)f.length()]; f.readFully(b); final HttpHeaders headers = new HttpHeaders(); headers.setContentType(MediaType.IMAGE_PNG); return new ResponseEntity<byte[]>(b, headers, HttpStatus.CREATED); } 

为我工作。

我赞成这一个:

 private ResourceLoader resourceLoader = new DefaultResourceLoader(); @ResponseBody @RequestMapping(value = "/{id}", produces = "image/bmp") public Resource texture(@PathVariable("id") String id) { return resourceLoader.getResource("classpath:images/" + id + ".bmp"); } 

将媒体types更改为您拥有的任何图像格式。

这在春季4是适合我的。

 @RequestMapping(value = "/image/{id}", method = RequestMethod.GET) public void findImage(@PathVariable("id") String id, HttpServletResponse resp){ final Foto anafoto = <find object> resp.reset(); resp.setContentType(MediaType.IMAGE_JPEG_VALUE); resp.setContentLength(anafoto.getImage().length); final BufferedInputStream in = new BufferedInputStream(new ByteArrayInputStream(anafoto.getImageInBytes())); try { FileCopyUtils.copy(in, resp.getOutputStream()); resp.flushBuffer(); } catch (final IOException e) { // TODO Auto-generated catch block e.printStackTrace(); } } 

没有答案为我工作,所以我设法做到这一点:

 HttpHeaders headers = new HttpHeaders(); headers.setContentType(MediaType.parseMediaType("your content type here")); headers.set("Content-Disposition", "attachment; filename=fileName.jpg"); headers.setContentLength(fileContent.length); return new ResponseEntity<>(fileContent, headers, HttpStatus.OK); 

设置Content-Disposition头我可以用我的方法下载带有@ResponseBody注解的文件。

这就是我用Spring Boot和Guava做的事情:

 @RequestMapping(value = "/getimage", method = RequestMethod.GET, produces = MediaType.IMAGE_JPEG_VALUE) public void getImage( HttpServletResponse response ) throws IOException { ByteStreams.copy( getClass().getResourceAsStream( "/preview-image.jpg" ), response.getOutputStream() ); } 

在spring4,很容易,你不需要在豆做任何改变。 只将您的返回types标记为@ResponseBody。

例:-

 @RequestMapping(value = "/image/{id}") public @ResponseBody byte[] showImage(@PathVariable Integer id) { byte[] b; /* Do your logic and return */ return b; }