Как отправить изображение с веб-службы в Spring

Я сталкиваюсь с проблемой при отправке изображения с помощью Spring веб-службы.

Я написал контроллер, как показано ниже

@Controller
public class WebService {

    @RequestMapping(value = "/image", headers = "Accept=image/jpeg, image/jpg, image/png, image/gif", method = RequestMethod.GET)
    public @ResponseBody byte[] getImage() {
        try {
            InputStream inputStream = this.getClass().getResourceAsStream("myimage.jpg");
            BufferedImage bufferedImage = ImageIO.read(inputStream);
            ByteArrayOutputStream byteArrayOutputStream = new ByteArrayOutputStream();
            ImageIO.write( bufferedImage  , "jpg", byteArrayOutputStream);
            return byteArrayOutputStream.toByteArray();

        } catch (IOException e) {
            throw new RuntimeException(e);
        }
    }
}

@ResponseBody преобразует ответ в JSON.

Я использую RestClient для проверки веб-службы.

Но когда я нажимаю URL http://localhost:8080/my-war-name/rest/image.

Header 
Accept=image/jpg

Я сталкиваюсь с следующей ошибкой в ​​RestClient

Ошибка преобразования тела ответа в строку с использованием кодировки Windows-1252. Тело ответа не установлено!

Когда я использую браузеры Chrome и Firefox

Заголовки не добавляются, поэтому ожидалась ошибка (просьба проинформировать меня об этом)

HTTP Status 405 - Request method 'GET' not supported

type Status report

message Request method 'GET' not supported

description The specified HTTP method is not allowed for the requested resource (Request method 'GET' not supported).

Я также столкнулся с ошибкой ниже

Ресурс, идентифицированный этим запросом, способен только генерирования ответов с характеристиками, неприемлемыми в соответствии с запросом "принять" заголовки()

Я следил http://krams915.blogspot.com/2011/02/spring-3-rest-web-service-provider-and.html учебник.

Мое требование - отправить изображение в байтовом формате в Android Client.

Ответ 1

В дополнение к ответу, предоставленному soulcheck. Spring добавил свойство yield в примечание @RequestMapping. Поэтому решение теперь проще:

@RequestMapping(value = "/image", method = RequestMethod.GET, produces = "image/jpg")
public @ResponseBody byte[] getFile()  {
    try {
        // Retrieve image from the classpath.
        InputStream is = this.getClass().getResourceAsStream("/test.jpg"); 

        // Prepare buffered image.
        BufferedImage img = ImageIO.read(is);

        // Create a byte array output stream.
        ByteArrayOutputStream bao = new ByteArrayOutputStream();

        // Write to output stream
        ImageIO.write(img, "jpg", bao);

        return bao.toByteArray();
    } catch (IOException e) {
        logger.error(e);
        throw new RuntimeException(e);
    }
}

Ответ 2

Ответ #soulcheck частично прав. Конфигурация не будет работать в последней версии Spring, поскольку она столкнулась бы с элементом mvc-annotation. Попробуйте следующую конфигурацию.

<mvc:annotation-driven>
  <mvc:message-converters register-defaults="true">
    <bean class="org.springframework.http.converter.BufferedImageHttpMessageConverter"/>
  </mvc:message-converters>
</mvc:annotation-driven>

Как только вы настроите конфигурацию в своем файле конфигурации. Ниже приведен код:

@RequestMapping(value = "/image", headers = "Accept=image/jpeg, image/jpg, image/png, image/gif", method = RequestMethod.GET)
public @ResponseBody BufferedImage getImage() {
    try {
        InputStream inputStream = this.getClass().getResourceAsStream("myimage.jpg");
        return ImageIO.read(inputStream);
    } catch (IOException e) {
        throw new RuntimeException(e);
    }
}

Ответ 3

Перенести преобразование в json и отправить массив байтов как есть.

Единственный недостаток заключается в том, что он отправляет тип контента application/octet-stream по умолчанию.

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

Затем вы можете изменить свой метод на:

@RequestMapping(value = "/image", headers = "Accept=image/jpeg, image/jpg, image/png, image/gif", method = RequestMethod.GET)
public @ResponseBody BufferedImage getImage() {
    try {
        InputStream inputStream = this.getClass().getResourceAsStream("myimage.jpg");
        return ImageIO.read(inputStream);


    } catch (IOException e) {
        throw new RuntimeException(e);
    }
}

имея:

 <bean class="org.springframework.web.servlet.mvc.annotation.AnnotationMethodHandlerAdapter">
    <property name="order" value="1"/>
    <property name="messageConverters">
        <list>
            <bean class="org.springframework.http.converter.BufferedImageHttpMessageConverter"/>
        </list>
    </property>
</bean>

в конфигурации spring.

Ответ 4

Смотрите эту статью на превосходном сайте baeldung.com.

Вы можете использовать следующий код в своем контроллере Spring:

@RequestMapping(value = "/rest/getImgAsBytes/{id}", method = RequestMethod.GET)
public ResponseEntity<byte[]> getImgAsBytes(@PathVariable("id") final Long id, final HttpServletResponse response) {
    HttpHeaders headers = new HttpHeaders();
    headers.setCacheControl(CacheControl.noCache().getHeaderValue());
    response.setContentType(MediaType.IMAGE_JPEG_VALUE);

    try (InputStream in = imageService.getImageById(id);) { // Spring service call
        if (in != null) {
            byte[] media = IOUtils.toByteArray(in);
            ResponseEntity<byte[]> responseEntity = new ResponseEntity<>(media, headers, HttpStatus.OK);
            return responseEntity;
        }
    } catch (IOException e) {
        e.printStackTrace();
    }
    return new ResponseEntity<>(null, headers, HttpStatus.NOT_FOUND);
}

Примечания: IOUtils происходит из библиотеки common-io apache. Я использую службу Spring для извлечения img/pdf Blob из базы данных.

Аналогичная обработка файлов PDF, за исключением того, что вам нужно использовать MediaType.APPLICATION_PDF_VALUE в типе содержимого. И вы можете отсылать файл изображения или файл pdf со страницы html:

<html>
  <head>
  </head>
  <body>
    <img src="https://localhost/rest/getImgDetectionAsBytes/img-id.jpg" />
    <br/>
    <a href="https://localhost/rest/getPdfBatchAsBytes/pdf-id.pdf">Download pdf</a>
  </body>
</html>

... или вы можете вызвать метод веб-службы непосредственно из своего браузера.

Ответ 5

Здесь метод, который я написал для этого.

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

Document - моя модель сущности для представления документов. У меня есть файлы, которые хранятся на диске, названном после идентификатора записи, которая хранит этот документ. Исходное имя файла и тип mime хранятся в объекте Document.

@RequestMapping("/document/{docId}")
public void downloadFile(@PathVariable Integer docId, @RequestParam(value="inline", required=false) Boolean inline, HttpServletResponse resp) throws IOException {

    Document doc = Document.findDocument(docId);

    File outputFile = new File(Constants.UPLOAD_DIR + "/" + docId);

    resp.reset();
    if (inline == null) {
        resp.setHeader("Content-Disposition", "attachment; filename=\"" + doc.getFilename() + "\"");
    }
    resp.setContentType(doc.getContentType());
    resp.setContentLength((int)outputFile.length());

    BufferedInputStream in = new BufferedInputStream(new FileInputStream(outputFile));

    FileCopyUtils.copy(in, resp.getOutputStream());
    resp.flushBuffer();

}