【问题标题】:Detect "image corrupt or truncated" in Firefox在 Firefox 中检测“图像损坏或截断”
【发布时间】:2013-05-25 08:23:46
【问题描述】:

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

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

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

注意关于“离线”的部分。这就是我不能依赖浏览器缓存的原因。而且 HTML5 离线应用程序缓存不能满足我的需求,因为图像是响应式的。 (响应式图片与 HTML 离线应用缓存不兼容的解释见"Application Cache is a Douchebag"。)

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

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

以下是我如何遍历图片填充 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);
                    }
                }
            }
        }
    }

下面是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];
    }
};

最后,这里是我在 Firebug 中看到的内容的全文,更改了 URL 以保护有罪者:

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

【问题讨论】:

  • 它不会在&lt;img&gt; 元素上触发error 事件吗?
  • 有人可能会问,为什么您要尝试在本地存储中实现自己的图像缓存,而不是让浏览器缓存来发挥作用?
  • @jfriend00 我正在缓存图像以供离线使用。我在问题中说了这个,但我把它说成是旁白。我已经编辑了这个问题,以更加强调离线。无论如何,下一个明显的问题是为什么不使用 HTML5 离线应用缓存。关于为什么响应式图像和 HTML5 离线应用缓存不兼容的解释,请参阅alistapart.com/articles/application-cache-is-a-douchebag
  • @MaxArt 不,错误事件不会触发。我已编辑问题以包含错误处理程序代码和指示它不会触发的文本。我相信错误事件和加载事件在图像元素上是互斥的。我想 Firefox 选择在加载损坏或截断的图像时触发加载事件。无论如何,这与我所看到的一致。

标签: javascript firefox canvas local-storage picturefill


【解决方案1】:

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

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

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

不幸的是,Firefox 将 this.complete 设置为 true,所以这也不是一个选项。

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

【讨论】:

  • 不幸的是,当时 this.complete 也是如此,所以这并不能解决问题。我认为发生的情况是,一旦 .complete 设置为 true,Firefox 在 src 更改时永远不会将其设置为 false。哈伦夫。感谢您提及 HTML5 规范。我得去看看。我认为这是模棱两可的,但如果不是,也许是时候提交一个错误了!
  • 确实,我自己试过了,complete 标志仍然是true,它是只读的,不能手动改回来。因此,要么等待 Firefox 修复此错误,要么您可以在每次更改 src 并替换旧元素时创建一个新的 img 元素。
  • 实际上,在尝试示例时,我注意到更改src 时没有收到load 事件,并且图像未完全加载。在 Linux 上的 FF 14.0.1 上测试,使用 png 和 jpg 图像。我创建了this jsfiddle 来尝试一下,打开 Firebug 并观察控制台中记录了哪些事件。
  • 重复使用相同img 元素的另一个缺点(?)是,在第一次加载后,您看不到图像随后流式传输的部分结果,它将被完全替换一旦完成下载。但这实际上可能是您想要的。
  • 我在 jsfiddle 中看到了和你一样的东西。这表明问题不在于图像事件触发,而在于画布与 img 的交互。 (好吧,要么这样,要么我只是在某个地方犯了一个大错误,还没有看到它。)今天晚些时候,当我有时间的时候,我肯定会搞得更糟。现在得跑了....非常感谢您对此事的所有调查!
【解决方案2】:

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

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

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

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

【讨论】:

  • 这也为我修复了它。奇怪!
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2016-05-12
  • 2017-03-02
  • 2012-04-13
  • 2012-01-18
  • 1970-01-01
相关资源
最近更新 更多