Javascript 在 Firefox 中检测“图像损坏或截断”

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/11928878/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-24 07:43:11  来源:igfitidea点击:

Detect "image corrupt or truncated" in Firefox

javascriptfirefoxcanvaslocal-storagepicturefill

提问by Trott

(Pre-emptive strike: If you're tempted to mark this as a duplicate, note that other questions seem to ask "why am I getting this error?" I know why I'm getting this error; I want to know how I can detect the error in my JavaScript code. It only appears in the Firebug console and, of course, is obvious to the user when the image is loaded.)

(先发制人:如果您想将其标记为重复,请注意其他问题似乎在问“为什么我会收到此错误?”我知道我为什么会收到此错误;我想知道我是如何可以检测到我的 JavaScript 代码中的错误。它只出现在 Firebug 控制台中,当然,在加载图像时对用户来说是显而易见的。)

I am using picturefillfor responsive images. I have a callback that is fired for the load event on the images. So the callback runs every time someone resizes the browser window such that a different image is loaded via picturefill.

我正在为响应式图像使用图片填充。我有一个为图像上的加载事件触发的回调。因此,每次有人调整浏览器窗口大小以通过图片填充加载不同的图像时,回调都会运行。

Inside the callback, I'm converting the image data to a dataURL via canvas so that I can cache the image data in localStorage so its available to the user even when they are offline.

在回调中,我通过画布将图像数据转换为 dataURL,以便我可以将图像数据缓存在 localStorage 中,以便用户即使在离线时也可以使用它。

Note the part about "offline". That's why I cannot rely on the browser cache.And the HTML5 offline application cache doesn't meet my needs because the images are responsive. (See "Application Cache is a Douchebag"for the explanation of the incompatibility of responsive images with HTML offline application cache.)

注意关于“离线”的部分。这就是我不能依赖浏览器缓存的原因。而且 HTML5 离线应用程序缓存不能满足我的需求,因为图像是响应式的。(有关响应式图像与 HTML 离线应用程序缓存不兼容的解释,请参阅“应用程序缓存是一个混蛋”。)

On Firefox 14.0.1 on a Mac, the load image will fire if I resize the browser to something really big and then resize it back down to something small again before the large image has a chance to fully load. It ends up reporting "Image corrupt or truncated" in the Firebug console, but doesn't throw an exception or trigger an error event. No indication anything is wrong in the code. Just in the Firebug console. Meanwhile, it stores a truncated image in localStorage.

在 Mac 上的 Firefox 14.0.1 上,如果我将浏览器的大小调整为非常大的大小,然后在大图像有机会完全加载之前再次将其重新调整为较小的大小,则会触发加载图像。它最终会在 Firebug 控制台中报告“图像损坏或截断”,但不会引发异常或触发错误事件。没有迹象表明代码中有任何错误。就在 Firebug 控制台中。同时,它将截断的图像存储在 localStorage 中。

How can I reliably and efficiently detect this problem within JavaScript so that I don't cache that image?

如何在 JavaScript 中可靠有效地检测此问题,以免缓存该图像?

Here's how I loop through the picturefill divs to find img tags that have been inserted by picturefill:

下面是我如何遍历图片填充 div 以查找已被图片填充插入的 img 标签:

    var errorLogger = function () {
        window.console.log('Error loading image.');
        this.removeEventListener('load', cacheImage, false);
    };

    for( var i = 0, il = ps.length; i < il; i++ ){
        if( ps[ i ].getAttribute( "data-picture" ) !== null ){

            image = ps[ i ].getElementsByTagName( "img" )[0];
            if (image) {
                if ((imageSrc = image.getAttribute("src")) !== null) {
                    if (imageSrc.substr(0,5) !== "data:") {
                        image.addEventListener("load", cacheImage, false);
                        image.addEventListener('error', errorLogger, false);
                    }
                }
            }
        }
    }

And here's what the cacheImage()callback looks like:

这是cacheImage()回调的样子:

var cacheImage = function () {
    var canvas,
        ctx,
        imageSrc;

    imageSrc = this.getAttribute("src");

    if ((pf_index.hasOwnProperty('pf_s_' + imageSrc)) ||
        (imageSrc.substr(0,5) === "data:") ||
        (imageSrc === null) || (imageSrc.length === 0)) {
            return;
    }

    canvas = w.document.createElement("canvas");
    canvas.width = this.width;
    canvas.height = this.height;

    ctx = canvas.getContext("2d");
    ctx.drawImage(this, 0, 0);
    try {
        dataUri = canvas.toDataURL();
    } catch (e) {
        // TODO: Improve error handling here. For now, if canvas.toDataURL()
        //   throws an exception, don't cache the image and move on.
        return;
    }

    // Do not cache if the resulting cache item will take more than 128Kb.
    if (dataUri.length > 131072) {
        return;
    }

    pf_index["pf_s_"+imageSrc] = 1;

    try {
        localStorage.setItem("pf_s_"+imageSrc, dataUri);
        localStorage.setItem("pf_index", JSON.stringify(pf_index));
    } catch (e) {
        // Caching failed. Remove item from index object so next cached item
        //   doesn't wrongly indicate this item was successfully cached.
        delete pf_index["pf_s_"+imageSrc];
    }
};

Lastly, here is the full text of what I am seeing in Firebug with the URL changed to protect the guilty:

最后,这是我在 Firebug 中看到的内容的全文,其中 URL 已更改以保护罪犯:

Image corrupt or truncated: http://www.example.com/pf/external/imgs/extralarge.png

图像损坏或截断:http: //www.example.com/pf/external/imgs/extralarge.png

采纳答案by Sergiu Dumitriu

It appears that when changing the srcattribute of the imgtag, Firefox fires a loadevent. This is contrary to the HTML5 specification, which saysthat if the src attribute is changed, then any other fetch already in progress should be ended (which Firefox does), and no events should be sent. The loadevent should be sent only if the fetch was completed successfully. So I'd say that the fact that you get a loadevent is a Firefox bug.

似乎在更改标签的src属性时img,Firefox 会触发一个load事件。这与 HTML5 规范相反,该规范表示如果 src 属性被更改,则任何其他正在进行的提取都应该结束(Firefox 会这样做),并且不应该发送任何事件。load仅当提取成功完成时才应发送该事件。所以我会说你收到一个load事件是一个 Firefox 错误。

However, the image shouldknow if it is fully available or not, you could try to use the completeattribute:

但是,图像应该知道它是否完全可用,您可以尝试使用该complete属性:

if (this.complete === false) {
  return;
}

Unfortunately, Firefox has this.completeset to trueinstead, so that's not an option either.

不幸的是,Firefox 已this.complete设置为true改为,因此这也不是一个选项。

The best option may be to create a new <img>element each time you wish to change the srcattribute.

最好的选择可能是<img>每次您希望更改src属性时都创建一个新元素。

回答by Sergey S

I was dumbfounded by this issue today myself. Everything was working fine (the images loaded visually as expected) except that the error kept showing up in Firefox error console - no such errors in IE or Chrome though.

今天我自己也被这个问题弄糊涂了。一切正常(图像按预期在视觉上加载),除了错误一直显示在 Firefox 错误控制台中 - 不过在 IE 或 Chrome 中没有此类错误。

In my case I was plugging an image into a div with innerHtml in an on complete jquery handler. The errors stopped when I preempted the jquery call with:

在我的例子中,我在一个完整的 jquery 处理程序中将一个图像插入到一个带有 innerHtml 的 div 中。当我用以下命令抢占 jquery 调用时,错误停止了:

var image_holder = new Image();
image_holder.src = img_path;//path of image that's going to be plugged in  

It worked for me, but it still makes no sense. I assume it's something to do with timing as this code initiates the image to load before it gets to the code that actually plugs it into the page.

它对我有用,但仍然没有意义。我认为这与时间有关,因为此代码在到达实际将其插入页面的代码之前启动要加载的图像。