Java 如何在 Spring Boot 控制器中返回图像并像文件系统一样提供服务
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/40557637/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
How to return an image in Spring Boot controller and serve like a file system
提问by Manish Patel
I've tried the various ways given in Stackoverflow, maybe I missed something.
我已经尝试了 Stackoverflow 中给出的各种方法,也许我错过了一些东西。
I have an Android client (whose code I can't change) which is currently getting an image like this:
我有一个 Android 客户端(我无法更改其代码),它目前正在获取如下图像:
HttpURLConnection connection = (HttpURLConnection) url.openConnection();
connection.setRequestMethod("GET");
connection.connect();
Where url
is the location of the image (static resource on CDN). Now my Spring Boot API endpoint needs to behave like a file resource in the same way so that the same code can get images from the API (Spring boot version 1.3.3).
url
图片的位置在哪里(CDN上的静态资源)。现在,我的 Spring Boot API 端点需要以相同的方式像文件资源一样运行,以便相同的代码可以从 API(Spring Boot 版本 1.3.3)获取图像。
So I have this:
所以我有这个:
@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);
}
Now when the Android code tries to get http://someurl/image1.jpg
I get this error in my logs:
现在,当 Android 代码尝试获取http://someurl/image1.jpg
我的日志中出现此错误时:
Resolving exception from handler [public org.springframework.http.ResponseEntity com.myproject.MyController.getImage(java.lang.String)]: org.springframework.web.HttpMediaTypeNotAcceptableException: Could not find acceptable representation
解决处理程序异常 [public org.springframework.http.ResponseEntity com.myproject.MyController.getImage(java.lang.String)]: org.springframework.web.HttpMediaTypeNotAcceptableException: 找不到可接受的表示
Same error happens when I plug http://someurl/image1.jpg
into a browser.
当我插入http://someurl/image1.jpg
浏览器时发生同样的错误。
Oddly enough my tests check out ok:
奇怪的是,我的测试结果正常:
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
How do I get this to behave like an image being served up in the normal way? (Note I can't change the content-type header that the android code is sending)
我如何让它表现得像以正常方式提供的图像?(请注意,我无法更改 android 代码发送的内容类型标头)
EDIT
编辑
Code after comments (set content type, take out produces
):
注释后的代码(设置内容类型,取出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);
}
In a browser this just seems to give a stringified junk (byte to chars i guess). In Android it doesn't error, but the image doesn't show.
在浏览器中,这似乎只是给出了一个字符串化的垃圾(我猜是字节到字符)。在 Android 中,它不会出错,但不会显示图像。
采纳答案by Manish Patel
Finally fixed this... I had to add a ByteArrayHttpMessageConverter
to my WebMvcConfigurerAdapter
subclass:
终于解决了这个问题......我不得不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);
}
回答by Roman
I believe this should work:
我相信这应该有效:
@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);
}
Notice that the content-type is set for ResponseEntity
, not for HttpServletResponse
directly.
请注意,内容类型设置为ResponseEntity
,而不是HttpServletResponse
直接设置。
回答by mavriksc
In case you don't know the file/mime type you can do this.... I've done this where i take an uploaded file and replace the file name with a guid and no extension and browsers / smart phones are able to load the image no issues. the second is to serve a file to be downloaded.
如果您不知道文件/mime 类型,您可以执行此操作......加载图像没有问题。第二个是提供要下载的文件。
@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()));
}
}
UPDATEin java 9+ you need to add compile 'com.sun.activation:javax.activation:1.2.0'
to your dependencies this has also been moved or picked up by jakarta.see this post
在 Java 9+ 中更新您需要将其添加compile 'com.sun.activation:javax.activation:1.2.0'
到您的依赖项中,这也已被雅加达移动或拾取。看到这个帖子
回答by devyJava
Using Apache Commons, you can do this and expose the image on an endpoint
使用 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);
}
All images will be served at endpoint /image/{imageid}
所有图像都将在端点提供 /image/{imageid}