Spring MVC: как вернуть изображение в @ResponseBody? - PullRequest
130 голосов
/ 17 апреля 2011

Я получаю данные изображения (как byte[]) из БД.Как вернуть это изображение в @ResponseBody?

РЕДАКТИРОВАТЬ

Я сделал это без @ResponseBody, используя HttpServletResponse в качестве параметра метода:

@RequestMapping("/photo1")
public void photo(HttpServletResponse response) throws IOException {
    response.setContentType("image/jpeg");
    InputStream in = servletContext.getResourceAsStream("/images/no_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("/images/no_image.jpg");
    return IOUtils.toByteArray(in);
}

Ответы [ 14 ]

93 голосов
/ 24 мая 2013

если вы используете Spring версии 3.1 или новее, вы можете указать «производит» в аннотации @RequestMapping. Пример ниже работает для меня из коробки. Нет необходимости конвертировать регистр или что-либо еще, если у вас включен веб-mvc (@EnableWebMvc).

@ResponseBody
@RequestMapping(value = "/photo2", method = RequestMethod.GET, produces = MediaType.IMAGE_JPEG_VALUE)
public byte[] testphoto() throws IOException {
    InputStream in = servletContext.getResourceAsStream("/images/no_image.jpg");
    return IOUtils.toByteArray(in);
}
71 голосов
/ 16 февраля 2015

В Spring 4.1 и более поздних версиях вы можете вернуть практически все, что угодно (например, изображения, PDF-файлы, документы, банки, почтовые индексы и т. Д.), Без каких-либо дополнительных зависимостей. Например, следующий метод может быть способом возврата изображения профиля пользователя из 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()));
}

На что обратить внимание:

  • ResponseEntity с InputStreamResource в качестве типа возврата

  • Создание стиля построителя ResponseEntity

При использовании этого метода вам не нужно беспокоиться об автоматической разводке в HttpServletResponse, создании исключения IOException или копировании потоковых данных.

58 голосов
/ 13 декабря 2011

В дополнение к регистрации ByteArrayHttpMessageConverter вы можете использовать ResponseEntity вместо @ResponseBody. У меня работает следующий код:

@RequestMapping("/photo2")
public ResponseEntity<byte[]> testphoto() throws IOException {
    InputStream in = servletContext.getResourceAsStream("/images/no_image.jpg");

    final HttpHeaders headers = new HttpHeaders();
    headers.setContentType(MediaType.IMAGE_PNG);

    return new ResponseEntity<byte[]>(IOUtils.toByteArray(in), headers, HttpStatus.CREATED);
}
16 голосов
/ 26 октября 2012

Используя Spring 3.1.x и 3.2.x, вы должны это сделать:

Метод контроллера:

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

А аннотация mvc в файле servlet-context.xml:

<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>
11 голосов
/ 26 августа 2015

В дополнение к паре ответов здесь приведено несколько указателей (Spring 4.1).

В случае, если в вашем WebMvcConfig не настроены конвертеры сообщений, ResponseEntity внутри вашего @ResponseBody работает хорошо.

Если вы это сделаете, то есть вы настроили MappingJackson2HttpMessageConverter (как и я), используя ResponseEntity, возвращает org.springframework.http.converter.HttpMessageNotWritableException.

Единственное рабочее решение в этом случае - обернуть byte[] в @ResponseBody следующим образом:

@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;
}

В этом случае не забудьте правильно сконфигурировать конвертеры сообщений (и добавьте ByteArrayHttpMessageConverer) в ваш WebMvcConfig, например:

@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;
}
6 голосов
/ 17 мая 2015
 @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);



}

работал для меня.

6 голосов
/ 17 апреля 2011

В контексте вашего приложения объявите 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> 

также в методе обработчика задайте соответствующий тип содержимого для вашего ответа.

4 голосов
/ 08 ноября 2015

Я предпочитаю это:

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");
}

Измените тип носителя на любой формат изображения, который у вас есть.

3 голосов
/ 27 апреля 2015

Это работа для меня весной 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();
        }

}
2 голосов
/ 16 апреля 2015

Ни один из ответов не работал для меня, поэтому мне удалось сделать это так:

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 намой метод.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...