如果图像尺寸很大,则不会加载图像
我使用MEDIUMBLOB在DB中存储图像。 当我尝试通过servlet加载图像时,我能够看到这些图像。 但是,如果图像大小很大(1 MB或更多),我可以在浏览器上看到一半或三分之一的图像。
当我下载相同的图像并将其放入公共webcontent时,它完美地工作。 知道如何克服这个问题吗? 我需要在servlet或MySQL中设置任何变量吗?
(JSF生成的)HTML代码如下:
图像servlet执行以下操作:
String imgLen = rs1.getString(1); int len = imgLen.length(); byte[] rb = new byte[len]; InputStream readImg = rs1.getBinaryStream(1); InputStream inputStream = readImg; int index = readImg.read(rb, 0, len); response.reset(); response.setHeader("Content-Length", String.valueOf(len)); response.setHeader("Content-disposition", "inline;filename=/file.png"); response.setContentType("image/png"); response.getOutputStream().write(rb, 0, len); response.getOutputStream().flush();
编辑1
当我使用下面的代码并将文件保存到本地磁盘时,我看到完整的图像。
String imgLen = rs1.getString(1); int len = imgLen.length(); rb = new byte[len]; inputStream = rs1.getBinaryStream(1); while ((read = inputStream.read(rb)) != -1) { out.write(rb, 0, read); } out.flush(); out.close();
编辑2
当我保存一半观看的图像时,我注意到这些图像的大小是100KB 。 我的1 MB图像显示大小为100KB。 这发生在所有图像:(
我认为这是最大的暗示发生了什么错误。 但我没有弄错。
编辑3
如果我从web.xml
删除下面的内容,我可以查看这些图像。
MyFacesExtensionsFilter org.apache.myfaces.webapp.filter.ExtensionsFilter MyFacesExtensionsFilter Faces Servlet
我可以删除那些吗? 我没有重新收集为什么我添加了这些……
编辑4
我的web.xml文件是
javax.faces.PROJECT_STAGE Development Faces Servlet javax.faces.webapp.FacesServlet 1 Faces Servlet /faces/* 60 faces/index.xhtml restrict com.sac.filter.MyFilter restrict *.xhtml MyFacesExtensionsFilter org.apache.myfaces.webapp.filter.ExtensionsFilter MyFacesExtensionsFilter Faces Servlet DisplayImage com.sac.databean.DisplayImage DisplayImage /DisplayImage SaveMyImage com.sac.databean.SaveMyImage SaveMyImage /SaveMyImage
测量图像长度的方式是错误的。 您基本上将图像字节转换为人类可读的字符(以无法理解的顺序,但旁边),然后计算字符数。 这个不对。 您需要计算原始和未转换字节的数量。 一个字符不一定仅由一个字节表示,但它可以由多个字节表示。
有两种方法可以解决您的问题:
-
请改用
ResultSet#getBytes()
。byte[] content = resultSet.getBytes("content"); // ... response.setContentLength(content.length); response.getOutputStream().write(content);
请注意,这是内存占用,因为
byte[]
每个byte
基本上都会累积Java内存的一个字节。 -
在查询中也选择BLOB长度。 怎么做取决于使用的数据库。 在MySQL中,您可以使用
LENGTH()
函数。SELECT content, LENGTH(content) AS contentLength FROM image WHERE id = ?
然后您按以下方式处理:
InputStream content = resultSet.getBinaryStream("content"); int contentLength = resultSet.getInt("contentLength"); // ... response.setContentLength(contentLength); SomeUtil.streamByBuffer(content, response.getOutputStream());
(其中该过程不是通过完整图像长度的
byte[]
进行的)
更新 :毕竟,对图像的请求似乎调用了MyFacesExtensionsFilter
,当chain.doFilter()
返回时,它显然过度缓冲响应而没有正确刷新它。 此筛选器符合仅在调用FacesServlet
时调用的映射规则。 但这不应该发生。 图像请求应该只调用图像servlet,而不是面部servlet。
根据映射规则,当您的图像servlet映射到/DisplayImage
,将在/faces/*
上调用FacesServlet
。 你所在的是相对于当前请求的URL,所以它最终会成为
/faces/DisplayImage
,它将首先调用FacesServlet
,然后调用DisplayImage
servlet。 这是错的。
您应该相应地更改JSF代码,以便最终变为域相关,以便它只调用
/DisplayImage
servlet。
您可以通过使用
的前导斜杠来实现此
。 它将自动添加上下文路径。