Подтвердить что ты не робот

Обнаружить "изображение поврежденным или усеченным" в Firefox

(Упреждающий удар: если у вас есть соблазн отметить это как дубликат, обратите внимание, что другие вопросы, похоже, задают вопрос: "Почему я получаю эту ошибку?" Я знаю, почему я получаю эту ошибку, я хочу знаю, как я могу обнаружить ошибку в моем JavaScript-коде. Он появляется только в консоли Firebug и, конечно же, является очевидным для пользователя при загрузке изображения.)

Я использую picturefill для реагирующих изображений. У меня есть обратный вызов, который запускается для события загрузки на изображениях. Таким образом, обратный вызов запускается каждый раз, когда кто-то изменяет размер окна браузера, так что другое изображение загружается через залив изображения.

Внутри обратного вызова я преобразую данные изображения в dataURL через холст, чтобы я мог кэшировать данные изображения в localStorage, чтобы он был доступен пользователю, даже когда он находится в автономном режиме.

Обратите внимание на часть "offline". Вот почему я не могу полагаться на кеш браузера. И кеш-приложение офлайн-кэша HTML5 не отвечает моим потребностям, потому что изображения реагируют. (См. "Кэш приложения - Douchebag" для объяснения несовместимости реагирующих изображений с кешем офлайн-приложений.)

В Firefox 14.0.1 на Mac изображение загрузки будет срабатывать, если я изменил размер браузера на что-то действительно большое, а затем изменил его размер до некоторого маленького размера, прежде чем у большого изображения появится возможность полностью загрузить. Он заканчивает сообщение "Изображение повреждено или усечено" в консоли Firebug, но не генерирует исключение или не вызывает событие ошибки. В коде нет ничего плохого. Просто в консоли Firebug. Тем временем он сохраняет усеченное изображение в localStorage.

Как я могу надежно и эффективно обнаруживать эту проблему в JavaScript, чтобы не кэшировать это изображение?

Здесь, как я прокручиваю divfilm, чтобы найти img теги, которые были вставлены с помощью 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);
                    }
                }
            }
        }
    }

И вот как выглядит обратный вызов 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

4b9b3361

Ответ 1

Похоже, что при изменении атрибута src тега img Firefox запускает событие load. Это противоречит спецификации HTML5, которая говорит, что если атрибут src изменен, то любая другая выборка, которая уже выполняется, должна быть завершена (какой Firefox), и никакие события не должны отправляться. Событие load следует отправлять только в том случае, если выборка выполнена успешно. Поэтому я бы сказал, что факт, что вы получаете событие load, является ошибкой Firefox.

Однако изображение должно знать, полностью ли оно доступно или нет, вы можете попробовать использовать атрибут complete:

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

К сожалению, Firefox имеет this.complete вместо true, так что это не вариант.

Лучшим вариантом может быть создание нового элемента <img> каждый раз, когда вы хотите изменить атрибут src.

Ответ 2

Я сам был ошеломлен этим вопросом. Все работало нормально (изображения загружались визуально, как и ожидалось), за исключением того, что ошибка продолжала отображаться в консоли ошибок Firefox - таких ошибок в IE или Chrome не было.

В моем случае я подключил изображение к div с innerHtml в полном обработчике jquery. Ошибки прекратились, когда я выгрузил вызов jquery с помощью:

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

Это сработало для меня, но это все еще бессмысленно. Я предполагаю, что это связано с синхронизацией, поскольку этот код инициирует загрузку изображения, прежде чем он попадет в код, который фактически подключает его к странице.