如何在 Spring Boot 控制器中返回图像并像文件系统一样提供服务

新手上路,请多包涵

我已经尝试了 Stackoverflow 中给出的各种方法,也许我错过了一些东西。

我有一个 Android 客户端(我无法更改其代码),它目前正在获取这样的图像:

 HttpURLConnection connection = (HttpURLConnection) url.openConnection();
connection.setRequestMethod("GET");
connection.connect();

其中 url 是图像的位置(CDN 上的静态资源)。现在我的 Spring Boot API 端点需要以相同的方式表现得像文件资源,以便相同的代码可以从 API(Spring Boot 版本 1.3.3)获取图像。

所以我有这个:

 @ResponseBody
@RequestMapping(value = "/Image/{id:.+}", method = RequestMethod.GET, consumes = MediaType.ALL_VALUE, produces = MediaType.IMAGE_JPEG_VALUE)
public ResponseEntity<byte[]> getImage(@PathVariable("id")String id) {
    byte[] image = imageService.getImage(id);  //this just gets the data from a database
    return ResponseEntity.ok(image);
}

现在,当 Android 代码尝试获取 http://someurl/image1.jpg 时,我在日志中收到此错误:

解决来自处理程序 [public org.springframework.http.ResponseEntity com.myproject.MyController.getImage(java.lang.String)] 的异常:org.springframework.web.HttpMediaTypeNotAcceptableException:找不到可接受的表示形式

当我将 http://someurl/image1.jpg 插入浏览器时,会发生同样的错误。

奇怪的是我的测试检查正常:

 Response response = given()
            .pathParam("id", "image1.jpg")
            .when()
            .get("MyController/Image/{id}");

assertEquals(HttpStatus.OK.value(), response.getStatusCode());
byte[] array = response.asByteArray(); //byte array is identical to test image

我如何让它表现得像以正常方式提供的图像? (注意我无法更改 android 代码发送的内容类型标头)

编辑

注释后的代码(设置内容类型, produces ):

 @RequestMapping(value = "/Image/{id:.+}", method = RequestMethod.GET, consumes = MediaType.ALL_VALUE)
public ResponseEntity<byte[]> getImage(@PathVariable("id")String id, HttpServletResponse response) {
    byte[] image = imageService.getImage(id);  //this just gets the data from a database
    response.setContentType(MediaType.IMAGE_JPEG_VALUE);
    return ResponseEntity.ok(image);
}

在浏览器中,这似乎给出了一个字符串化的垃圾(我猜是字节到字符)。在 Android 中它不会出错,但图像不会显示。

原文由 Manish Patel 发布,翻译遵循 CC BY-SA 4.0 许可协议

阅读 704
2 个回答

终于解决了这个问题……我不得不添加一个 ByteArrayHttpMessageConverter 到我的 WebMvcConfigurerAdapter 子类:

 @Override
public void configureMessageConverters(List<HttpMessageConverter<?>> converters) {
    final ByteArrayHttpMessageConverter arrayHttpMessageConverter = new ByteArrayHttpMessageConverter();
    final List<MediaType> list = new ArrayList<>();
    list.add(MediaType.IMAGE_JPEG);
    list.add(MediaType.APPLICATION_OCTET_STREAM);
    arrayHttpMessageConverter.setSupportedMediaTypes(list);
    converters.add(arrayHttpMessageConverter);

    super.configureMessageConverters(converters);
}

原文由 Manish Patel 发布,翻译遵循 CC BY-SA 3.0 许可协议

我相信这应该有效:

 @RequestMapping(value = "/Image/{id:.+}", method = RequestMethod.GET)
public ResponseEntity<byte[]> getImage(@PathVariable("id") String id) {
    byte[] image = imageService.getImage(id);
    return ResponseEntity.ok().contentType(MediaType.IMAGE_JPEG).body(image);
}

请注意,内容类型是为 ResponseEntity 设置的,而不是直接为 HttpServletResponse 设置的。

原文由 Roman 发布,翻译遵循 CC BY-SA 3.0 许可协议

撰写回答
你尚未登录,登录后可以
  • 和开发者交流问题的细节
  • 关注并接收问题和回答的更新提醒
  • 参与内容的编辑和改进,让解决方法与时俱进
推荐问题