繁体   English   中英

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

[英]How to return an image in Spring Boot controller and serve like a file system

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

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

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

其中url是图像的位置(CDN上的静态资源)。 现在,我的Spring Boot API端点需要以相同的方式表现得像文件资源,以便相同的代码可以从API获取图像(Spring引导版本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中它没有错误,但图像没有显示。

我相信这应该有效:

@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设置的。

最后解决了这个问题...我必须在我的WebMvcConfigurerAdapter子类中添加一个ByteArrayHttpMessageConverter

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

如果您不知道文件/ mime类型,您可以这样做....我已经这样做了我上传文件并用guid替换文件名,没有扩展名和浏览器/智能手机能够加载图像没有问题。 第二个是提供要下载的文件。

@RestController
@RequestMapping("img")
public class ImageController {

@GetMapping("showme")
public ResponseEntity<byte[]> getImage() throws IOException{
    File img = new File("src/main/resources/static/test.jpg");
    return ResponseEntity.ok().contentType(MediaType.valueOf(FileTypeMap.getDefaultFileTypeMap().getContentType(img))).body(Files.readAllBytes(img.toPath()));
}
@GetMapping("thing")
public ResponseEntity<byte[]> what() throws IOException{
    File file = new File("src/main/resources/static/thing.pdf");
    return ResponseEntity.ok()
            .header("Content-Disposition", "attachment; filename=" +file.getName())
            .contentType(MediaType.valueOf(FileTypeMap.getDefaultFileTypeMap().getContentType(file)))
            .body(Files.readAllBytes(file.toPath()));
}


}   

在java 9+中更新你需要将compile 'com.sun.activation:javax.activation:1.2.0'到你的依赖项中,这也被jakarta移动或拾取。 看这篇文章

使用Apache Commons,您可以执行此操作并在端点上公开图像

@RequestMapping(value = "/image/{imageid}",method= RequestMethod.GET,produces = MediaType.IMAGE_JPEG_VALUE)
public @ResponseBody byte[] getImageWithMediaType(@PathVariable int imageid) throws IOException {
    InputStream in = new ByteArrayInputStream(getImage(imageid));
    return IOUtils.toByteArray(in);
    }

所有图片都将在端点/image/{imageid}

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM