如果图像尺寸很大,则不会加载图像

我使用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   

测量图像长度的方式是错误的。 您基本上将图像字节转换为人类可读的字符(以无法理解的顺序,但旁边),然后计算字符数。 这个不对。 您需要计算原始和未转换字节的数量。 一个字符不一定仅由一个字节表示,但它可以由多个字节表示。

有两种方法可以解决您的问题:

  1. 请改用ResultSet#getBytes()

     byte[] content = resultSet.getBytes("content"); // ... response.setContentLength(content.length); response.getOutputStream().write(content); 

    请注意,这是内存占用,因为byte[]每个byte基本上都会累积Java内存的一个字节。

  2. 在查询中也选择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。

  

您可以通过使用的前导斜杠来实现此 。 它将自动添加上下文路径。