2012-08-13 19 views
15

(Golpe preventivo: si tiene la tentación de marcar esto como un duplicado, tenga en cuenta que otras preguntas parecen preguntar "¿por qué me sale este error?" Sé por qué Estoy obteniendo este error, quiero saber cómo puedo detectar el error en mi código JavaScript. Aparece solo en la consola Firebug y, por supuesto, es obvio para el usuario cuando se carga la imagen.)Detectar "imagen dañada o truncada" en Firefox

I Estoy usando picturefill para imágenes receptivas. Tengo una devolución de llamada que se activa para el evento de carga en las imágenes. Por lo tanto, la devolución de llamada se ejecuta cada vez que alguien cambia el tamaño de la ventana del navegador de forma que se cargue una imagen diferente a través del relleno de imagen.

Dentro de la devolución de llamada, estoy convirtiendo los datos de imagen a través de un DataURL tela para que pueda almacenar en caché los datos de imagen en localStorage por lo que su disponibles para el usuario incluso cuando están fuera de línea.

Tenga en cuenta la parte sobre "fuera de línea". Es por eso que no puedo confiar en el caché del navegador. Y el caché de aplicaciones sin conexión de HTML5 no satisface mis necesidades porque las imágenes son receptivas. (Consulte "Application Cache is a Douchebag" para la explicación de la incompatibilidad de imágenes receptivas con la caché de aplicaciones sin conexión HTML.)

En Firefox 14.0.1 en una Mac, la imagen de carga se activará si cambio el tamaño del navegador a algo realmente grande y luego lo cambio de tamaño vuelve a bajar a algo pequeño antes de que la imagen grande tenga la oportunidad de cargarse por completo. Termina informando "Imagen dañada o truncada" en la consola de Firebug, pero no arroja una excepción ni desencadena un evento de error. No hay indicación de que algo esté mal en el código. Solo en la consola Firebug. Mientras tanto, almacena una imagen truncada en localStorage.

¿Cómo puedo detectar de manera confiable y eficiente este problema dentro de JavaScript para que no guarde en caché esa imagen?

Así es como me bucle a través de los divs picturefill para encontrar las etiquetas img que han sido insertados por 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); 
        } 
       } 
      } 
     } 
    } 

Y aquí es lo que el cacheImage() devolución de llamada se parece a:

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]; 
    } 
}; 

Por último, aquí es el texto completo de lo que estoy viendo en Firebug con la URL modificada para proteger a los culpables:

de imagen dañado o truncado: http://www.example.com/pf/external/imgs/extralarge.png

+2

¿No desencadena un evento 'error' en el elemento' '? – MaxArt

+2

¿Uno podría preguntarse por qué está tratando de implementar su propio almacenamiento en caché de imágenes en el almacenamiento local en lugar de dejar que el caché del navegador lo haga funcionar? – jfriend00

+0

@ jfriend00 Estoy almacenando en caché la imagen para uso fuera de línea. Dije esto en la pregunta, pero lo expresé como un aparte. He editado la pregunta para darle más énfasis al bit fuera de línea. De todos modos, la siguiente pregunta obvia es por qué no utilizar la aplicación de aplicaciones HTML5 sin conexión. Para obtener una explicación sobre por qué las imágenes receptivas y la aplicación de aplicaciones fuera de línea de HTML5 son incompatibles, consulte http://www.alistapart.com/articles/application-cache-is-a-douchebag/ – Trott

Respuesta

9

Parece que cuando se cambia el atributo de la etiqueta srcimg, Firefox dispara un evento load. Esto es contrario a la especificación HTML5, que says indica que si se cambia el atributo src, se debe finalizar cualquier otra búsqueda que ya esté en curso (lo que hace Firefox), y no se deben enviar eventos. El evento load debe enviarse solo si la búsqueda se completó correctamente. Así que diría que el hecho de que obtienes un evento load es un error de Firefox.

Sin embargo, la imagen debe se sabe si está totalmente disponible o no, usted podría tratar de usar el atributo complete:

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

Desafortunadamente, Firefox ha this.complete conjunto de true lugar, por lo que no es una opción tampoco.

La mejor opción puede ser crear un nuevo elemento <img> cada vez que desee cambiar el atributo src.

+0

Desafortunadamente, this.complete también es cierto en ese momento, por lo que no se soluciona el problema. Creo que lo que está sucediendo allí es que una vez que se haya establecido. cierto, Firefox nunca lo establece en falso cuando se cambia src. Harrumph. Gracias por mencionar las especificaciones de HTML5. Tendré que verificarlo. Pensé que era ambiguo sobre esto, pero si no, tal vez es hora de presentar una ¡error! – Trott

+0

De hecho, lo intenté ahora mismo y la bandera 'completa' sigue siendo 'verdadera', y es de solo lectura, no puede ser cambiada manualmente. Así que o bien espere a que Firefox corrija este error, o puede crear un nuevo elemento 'img' cada vez que cambie' src' y reemplace el anterior. –

+0

En realidad, al probar el ejemplo, noté que no recibí un evento 'load' al cambiar el' src' y el la imagen no se cargó completamente. Probado en FF 14.0.1 en Linux, usando imágenes tanto png como jpg. Creé [este jsfiddl e] (http://jsfiddle.net/GfKCf/5/) para probarlo, abra Firebug y observe qué eventos están registrados en la consola. –

2

Hoy estuve estupefacto por este problema. Todo funcionaba bien (las imágenes se cargaban visualmente como se esperaba), excepto que el error seguía apareciendo en la consola de error de Firefox, sin embargo, no había errores en IE o Chrome.

En mi caso estaba conectando una imagen en un div con innerHtml en un controlador jquery completo. Los errores se detuvieron cuando se adelantó la llamada jQuery con:

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

Funcionó para mí, pero todavía no tiene ningún sentido. Supongo que tiene que ver con el tiempo ya que este código inicia la carga de la imagen antes de que llegue al código que realmente la conecta a la página.

+0

Esto lo arregló para mí también. ¡Extraño! –

Cuestiones relacionadas