【问题标题】:How to send an Image from Web Service in Spring如何在 Spring 中从 Web 服务发送图像
【发布时间】:2012-01-29 04:14:01
【问题描述】:

我在使用 Spring Web Service 发送图像时遇到问题。

我写的控制器如下

@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 测试 Web Service。

但是当我使用http://localhost:8080/my-war-name/rest/image URL 时。

Header 
Accept=image/jpg

我在 RestClient 上遇到以下错误

使用 windows-1252 编码将响应正文转换为字符串失败。未设置响应正文!

当我使用 Chrome 和 Firefox 浏览器时

未添加标题,因此预计会出错(请指导我)

HTTP 状态 405 - 不支持请求方法“GET” 类型状态报告 不支持消息请求方法“GET” 描述 请求的资源不允许指定的 HTTP 方法(不支持请求方法“GET”)。

我也遇到过一次以下错误

此请求标识的资源仅能 根据请求“接受”标头生成具有不可接受特征的响应()

我关注了 http://krams915.blogspot.com/2011/02/spring-3-rest-web-service-provider-and.html教程。

我的要求是以字节格式发送图像到Android客户端。

【问题讨论】:

标签: java json spring spring-mvc


【解决方案1】:

如果您使用的是 Spring Boot,只需将图像放在类路径中的正确文件夹中即可。检查https://www.baeldung.com/spring-mvc-static-resources

【讨论】:

    【解决方案2】:

    this article on the excellent baeldung.com website

    您可以在 Spring Controller 中使用以下代码:

    @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。您可以从 html 页面引用图像文件或 pdf 文件:

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

    ...或者您可以直接从浏览器调用网络服务方法。

    【讨论】:

      【解决方案3】:

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

      【讨论】:

        【解决方案4】:

        除了灵魂检查提供的答案。 Spring 已将 produces 属性添加到 @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);
            }
        }
        

        【讨论】:

          【解决方案5】:

          这是我为此编写的方法。

          我需要在页面上显示内联图像,并可选择将其下载到客户端,因此我采用了一个可选参数来为此设置适当的标题。

          Document 是我表示文档的实体模型。我将文件本身存储在以存储该文档的记录的 ID 命名的磁盘上。原始文件名和 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();
          
          }
          

          【讨论】:

            【解决方案6】:

            删除转换为 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 配置中。

            【讨论】:

              猜你喜欢
              • 1970-01-01
              • 1970-01-01
              • 1970-01-01
              • 2011-05-06
              • 2013-07-01
              • 2013-06-05
              • 1970-01-01
              • 1970-01-01
              • 1970-01-01
              相关资源
              最近更新 更多