检测“图像损坏或截断”在Firefox [英] Detect "image corrupt or truncated" in Firefox

查看:400
本文介绍了检测“图像损坏或截断”在Firefox的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

(先发制人罢工:如果你想把这标记为重复,注意其他问题似乎问为什么我得到这个错误?我知道为什么我得到这个错误;我想知道我如何检测我的JavaScript代码中的错误,它只出现在Firebug控制台,当然,是当用户加载图像时显而易见。)



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



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



请注意关于离线的部分。这就是为什么我不能依赖浏览器缓存。 HTML5离线应用缓存不能满足我的需要,因为图像是响应。 (有关响应式广告素材不兼容的说明,请参见应用程序缓存是一个Douchebag



在Mac上的Firefox 14.0.1上,如果我调整浏览器的大小,然后重新调整大小,加载图片将会触发在大图像有机会完全加载之前再次下降到小的东西。它最终在Firebug控制台中报告图像损坏或截断,但不会引发异常或触发错误事件。没有迹象表明代码中有什么错误。只是在Firebug控制台。



如何在JavaScript中可靠,高效地检测这个问题,以便我不缓存该图像? / strong>



这是我如何循环通过picturefill divs找到img标签已被插入picturefill:

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

for(var i = 0,il = ps.length; 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);
}
}
}
}
}


$ b b

下面是 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:改进错误处理。现在,如果canvas.toDataURL()
//抛出异常,不要缓存图像,继续前进。
return;
}

//不缓存,如果生成的缓存项目将需要超过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){
//缓存失败。从索引对象中删除项目,因此下一个高速缓存的项目
//不会错误地指示此项目已成功缓存。
delete pf_index [pf_s _+ imageSrc];
}
};

最后,这里是我在Firebug中看到的全文,有罪:


图片已毁损或已截断: http://www.example.com/pf/external/imgs/extralarge.png



解决方案

看来当改变 img 标签的 src 属性时, Firefox触发加载事件。这与HTML5规范相反,后者如果src属性被改变,那么已经在进行的任何其他提取都应该结束(Firefox会做),并且不应该发送任何事件。只有在成功完成提取后,才会发送 load 事件。所以我会说,你得到加载事件的事实是一个Firefox错误。



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

  if(this.complete === false){
return;不幸的是,Firefox的 this.complete c $ c>设置为 true ,因此也不是一个选项。



最好的选择是每次要更改 src 属性时,请创建一个新的< img> 元素。 $ b

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

I am using picturefill for 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.

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.)

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.

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

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

    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:

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:

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

解决方案

It appears that when changing the src attribute of the img tag, Firefox fires a load event. This is contrary to the HTML5 specification, which says that 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 load event should be sent only if the fetch was completed successfully. So I'd say that the fact that you get a load event is a Firefox bug.

However, the image should know if it is fully available or not, you could try to use the complete attribute:

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

Unfortunately, Firefox has this.complete set to true instead, so that's not an option either.

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

这篇关于检测“图像损坏或截断”在Firefox的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

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