Pet*_*háč 10 java browser servlets spring-mvc http-headers
我似乎遇到了一个有趣的问题,浏览器愉快地显示由我的Spring MVC Web应用程序生成的图像,只要我的控制器的URL设置为IMG标记的SRC,但在直接导航到URL时显示二进制数据.
我的Spring MVC Controller生成一些BufferedImage(缩略图),将其转换为byte[]并使用@ResponseBody控制器方法上的注释将其直接返回到响应主体.我已经注册了一个org.springframework.http.converter.ByteArrayHttpMessageConverter消息转换器,AnnotationMethodHandlerAdapter甚至将其supportedMediaTypes属性设置为image/jpeg,这实际上没有帮助,所以我在控制器方法中手动设置响应的Content-Type标头.
<img src="/images/thumbnail?id=1234" />
Run Code Online (Sandbox Code Playgroud)
工作正常并显示图像,但直接导航到图像的SRC(或右键单击图像并选择查看图像)最终会显示图像的原始数据.
根据Firebug,从对此 URL的请求(http:// localhost:8888/images/thumbnail?id = F0snPkvwhtDbl8eutbuq)收到的响应标头是:
HTTP/1.1 200 OK
Expires: Wed, 21 Dec 2011 12:39:07 GMT
Cache-Control: max-age=2592000
Content-Type: image/jpeg
Content-Length: 6998
Server: Jetty(6.1.10)
Run Code Online (Sandbox Code Playgroud)
最后一句话:在Firebug中,单击Response选项卡显示图像:-)我错过了什么?我认为浏览器接收内容类型和内容长度标题,知道期望jpeg图像,接收jpeg的原始数据,然后在空浏览器选项卡中显示jpeg.不知何故FF和Chrome正在显示收到的原始图像数据.
我正在使用的代码:
@RequestMapping(value = "thumbnail", method = { RequestMethod.GET })
@ResponseBody
public byte[] getImageThumbnail(@RequestParam("id") String documentId, HttpServletResponse response) {
try {
Document document = documentService.getDocumentById(documentId);
InputStream imageInputStream = new FileInputStream(document.getUri());
response.setContentType("image/jpeg");
BufferedImage img = ImageIO.read(imageInputStream);
ResampleOp resampleOp = new ResampleOp(THUMBNAIL_DIMENSION);
BufferedImage thumbnail = resampleOp.filter(img, null);
return getDataFromBufferedImage(thumbnail);
} catch (Throwable t) {
return null; //return no data if document not found or whatever other issues are encountered
}
}
private byte[] getDataFromBufferedImage(BufferedImage thumbnail) throws IOException {
ByteArrayOutputStream baos = new ByteArrayOutputStream();
try {
ImageIO.write(thumbnail, "jpg", baos);
baos.flush();
return baos.toByteArray();
} finally {
baos.close();
}
}
Run Code Online (Sandbox Code Playgroud)
=== UPDATE === 我已经按照@BalusC的建议并将生成缩略图的网址更改为实际的.jpg文件.这有所不同,现在我可以"保存图像为",文件名不再只是"缩略图"而是".jpg",这是好的.但是,Chrome和FF(我还没有开始在IE上测试)在将URL加载到新的选项卡/窗口时显示原始JFIF数据.尽管如此,当用户在新选项卡中选择查看图像时,图像仅显示URL是否在IMG标记的SRC属性中(并且由于浏览器缓存)(但仅当用户不刷新选项卡时,刷新选项卡才会重新获取JPEG并在窗口中显示原始数据).
编辑 我刚刚在IE9中对此进行了测试,这是唯一可以按预期工作的浏览器.我可以直接导航到URL并不断刷新页面,我可以看到我的控制器被点击,JPEG被加载到浏览器窗口中.优秀.现在要弄清楚FF/CR处理我发送的JPEG的方式有什么问题.
其他信息 我正在使用Spring版本3.0.6.RELEASE从Jetty运行Web应用程序
编辑
我已经通过不使用@ResponseBody而解决了我的问题BytArrayHttpMessageConverter- 我尝试在另一个线程中提出的解决方法在SO上 - 这就是直接将字节写入响应输出流:IOUtils.copy(imageInputStream, response.getOutputStream());这很简单并且有效,我仍然好奇什么是浏览器如何在<img>标签中加载响应但不直接在浏览器窗口中加载奇怪的问题.任何人都可以对此有所了解,我真的很想知道更多.我暂时没有回答这个问题.
小智 2
尝试将注释更新为:
@RequestMapping(value = "thumbnail", method = { RequestMethod.GET }, produces = {"image/jpeg"})
@ResponseBody
Run Code Online (Sandbox Code Playgroud)
注意produces属性。
希望有帮助。