我的Spring MVC控制器生成一些BufferedImage(缩略图),将其转换为byte [],并使用控制器方法上的@ResponseBody注释将其直接返回到响应体.我已经注册了一个org.springframework.http.converter.ByteArrayHttpMessageConverter消息转换器与AnnotationMethodHandlerAdapter,甚至将其supportedMediaTypes属性设置为image / jpeg,这不是真正的帮助,所以我正在手动设置响应的Content-Type头控制器方法.
<img src="/images/thumbnail?id=1234" />
工作正常并显示图像,但直接导航到图像的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)
最后一句话:在Firebug中,单击“响应”选项卡显示图像:-)我错过了什么?我以为浏览器接收到内容类型和内容长度标题,知道要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(); } }
===更新===
我已经遵循@ BalusC的建议,并更改了生成缩略图的URL,看起来像一个实际的.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>中加载响应是奇怪的问题是什么标签,但不直接在浏览器窗口中.任何人都可以提出更多的看法,我会很好奇地发现更多.我现在离开这个问题没有答案.
解决方法
@RequestMapping(value = "thumbnail",method = { RequestMethod.GET },produces = {"image/jpeg"}) @ResponseBody
注意产生属性.
希望有帮助.