如果图像尺寸很大,则不会加载图像 [英] Images won't load if they are of high size

查看:83
本文介绍了如果图像尺寸很大,则不会加载图像的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我使用MEDIUMBLOB在DB中存储图像。当我尝试通过servlet加载图像时,我能够看到这些图像。但是,如果图像大小很大(1 MB或更多),我可以在浏览器上看到一半或三分之一的图像。

I am storing images in DB using MEDIUMBLOB. When I try to load image through a servlet, I am able to see those images. However if the image size is big (1 MB or more), I can see half or 3/4th image on the browser.

当我下载相同的图像并将其放入在公共网站内容中,它完美无缺。知道如何克服这个问题吗?我是否需要在servlet或MySQL中设置任何变量?

When I download same image and put it in public webcontent, it works perfectly. Any idea how to overcome this issue? Do I need to set any variable in the servlet or MySQL?

(JSF生成的)HTML代码如下:

The (JSF-generated) HTML code is as follows:

<img src="DisplayImage?mainID=drawing" />

图片servlet执行以下操作:

The image servlet does the following:

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



当我在下方使用时代码并将文件保存到本地磁盘,我看到完整的图像。

Edit 1

When I use below code and save file to local disk, I see full Image.

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。所有图像都会发生这种情况:(

Edit 2

When I save the half viewed images I noticed that the size of those images are 100KB. My 1 MB image is showing size as 100KB. This is happening with all images :(

我认为这是最大的HINT会发生什么错误。但是我没有弄错。

I think this is biggest HINT what wrong is going on. BUT I am not getting what is wrong.

如果我从 web.xml 中删除​​以下内容,我可以查看这些图片。

If I remove below stuff from my web.xml, I am able to view those images.

<filter>
    <filter-name>MyFacesExtensionsFilter</filter-name>
    <filter-class>org.apache.myfaces.webapp.filter.ExtensionsFilter</filter-class>
</filter>
<filter-mapping>
    <filter-name>MyFacesExtensionsFilter</filter-name>
    <servlet-name>Faces Servlet</servlet-name>
</filter-mapping>

我可以删除那些吗?我不会重新收集为什么我添加了这些...

Can I remove those? I don't re-collect why exactly I added those...

我的web.xml文件是

My web.xml file is

<?xml version="1.0" encoding="UTF-8"?>
<web-app version="3.0" xmlns="http://java.sun.com/xml/ns/javaee" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-app_3_0.xsd">
    <context-param>
        <param-name>javax.faces.PROJECT_STAGE</param-name>
        <param-value>Development</param-value>
    </context-param>
    <servlet>
        <servlet-name>Faces Servlet</servlet-name>
        <servlet-class>javax.faces.webapp.FacesServlet</servlet-class>
        <load-on-startup>1</load-on-startup>
    </servlet>
    <servlet-mapping>
        <servlet-name>Faces Servlet</servlet-name>
        <url-pattern>/faces/*</url-pattern>
    </servlet-mapping>
    <session-config>
        <session-timeout>
            60
        </session-timeout>
    </session-config>
    <welcome-file-list>
        <welcome-file>faces/index.xhtml</welcome-file>
    </welcome-file-list>
    <filter>
        <filter-name>restrict</filter-name>
        <filter-class>com.sac.filter.MyFilter</filter-class>
    </filter>
    <filter-mapping>
        <filter-name>restrict</filter-name>
        <url-pattern>*.xhtml</url-pattern>
    </filter-mapping>
    <filter>
        <filter-name>MyFacesExtensionsFilter</filter-name>
        <filter-class>org.apache.myfaces.webapp.filter.ExtensionsFilter</filter-class>
    </filter>
    <filter-mapping>
        <filter-name>MyFacesExtensionsFilter</filter-name>
        <servlet-name>Faces Servlet</servlet-name>
    </filter-mapping>

    <servlet>
        <servlet-name>DisplayImage</servlet-name>
        <servlet-class>com.sac.databean.DisplayImage</servlet-class>
    </servlet>
    <servlet-mapping>
        <servlet-name>DisplayImage</servlet-name>
        <url-pattern>/DisplayImage</url-pattern>
    </servlet-mapping>
    <servlet>
        <servlet-name>SaveMyImage</servlet-name>
        <servlet-class>com.sac.databean.SaveMyImage</servlet-class>
    </servlet>
    <servlet-mapping>
        <servlet-name>SaveMyImage</servlet-name>
        <url-pattern>/SaveMyImage</url-pattern>
    </servlet-mapping>
</web-app>


推荐答案

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

The way how you measured the image's length is wrong. You're basically converting the image bytes to human readable characters (in an unintelligible sequence, but that aside) and then calculating the amount of characters. This is not right. You need to calculate the amount of raw and unconverted bytes instead. One character is not necessarily represented by only one byte, but it can be represented by more than one byte.

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

There are 2 ways to solve your problem:


  1. 使用 ResultSet#getBytes()代替。

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

请注意,这是每个字节一个 byte [] 基本上累积了Java内存的一个字节。

Please note that this is memory hogging as every byte of a byte[] basically accumulates one byte of Java's memory.

选择BLOB长度在查询中也是如此。怎么做取决于使用的数据库。在MySQL中,您可以使用 LENGTH()函数。

Select the BLOB length in the query as well. How to do that depends on the DB used. In MySQL, you can use the LENGTH() function for this.

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());

(其中该过程不是通过字节进行的[ ] 完整图片的长度)

(wherein the process is not taken place through a byte[] of full image's length)






更新:毕竟,图片上的请求似乎调用了 MyFacesExtensionsFilter ,这显然是在没有正确的情况下过度缓冲响应当 chain.doFilter()返回时刷新它。此过滤器符合仅在调用 FacesServlet 时调用的映射规则。但这不应该发生。图像请求应该只调用图像servlet,而不是面部servlet。


Update: after all, the request on the image seemed to have invoked the MyFacesExtensionsFilter which is apparently overzealously buffering the response without properly flushing it when the chain.doFilter() returns. This filter is according the mapping rules only invoked when the FacesServlet is invoked. But this shouldn't have happened. The image request should only have invoked the image servlet, not also the faces servlet.

根据映射规则, FacesServlet / DisplayImage 时,在 / faces / * 上调用c>。 < img src> 因为你有相对于当前请求的URL,所以它最终最终是 / faces / DisplayImage 将首先调用 FacesServlet ,然后调用 DisplayImage servlet。这是错误的。

According the mapping rules, the FacesServlet is invoked on /faces/* while your image servlet is mapped on /DisplayImage. The <img src> as you've there is relative to the current request URL, so it ultimately ends up to be /faces/DisplayImage which will first invoke the FacesServlet and then the DisplayImage servlet. This is wrong.

您应该相应地更改JSF代码,以便< img src> 最终成为域名-relative使它只调用 / DisplayImage servlet。

You should change the JSF code accordingly so that the <img src> ultimately becomes domain-relative so that it invokes only the /DisplayImage servlet.

<img src="/contextpath/DisplayImage?mainID=drawing" />

您只需使用中的前导斜杠< h:即可实现此目的: graphicImage的> 。它会自动添加上下文路径。

You can achieve this by just using the leading slash in <h:graphicImage>. It will auto-prepend the context path.

<h:graphicImage value="/DisplayImage?mainID=drawing" />

这篇关于如果图像尺寸很大,则不会加载图像的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆