2012-08-13 15 views
15

(Attacco preventivo: se si è tentati di contrassegnarlo come duplicato, si noti che altre domande sembrano chiedere "perché ottengo questo errore?". So perché sto ottenendo questo errore, voglio sapere come posso rilevare l'errore nel mio codice JavaScript, appare solo nella console Firebug e, ovviamente, è ovvio all'utente quando l'immagine viene caricata.)Rileva "immagine corrotta o troncata" in Firefox

I Sto usando picturefill per le immagini reattive. Ho un callback che viene attivato per l'evento load sulle immagini. Quindi la richiamata viene eseguita ogni volta che qualcuno ridimensiona la finestra del browser in modo tale che un'immagine diversa venga caricata tramite picturefill.

All'interno del callback, sto convertendo i dati dell'immagine in un dataURL tramite canvas in modo da poter memorizzare nella cache i dati dell'immagine in localStorage in modo che siano disponibili all'utente anche quando sono offline.

Nota la parte relativa a "non in linea". Ecco perché non posso fare affidamento sulla cache del browser. E la cache dell'applicazione offline HTML5 non soddisfa le mie esigenze perché le immagini sono reattive. (Vedere "Application Cache is a Douchebag" per la spiegazione dell'incompatibilità delle immagini reattive con cache di applicazioni offline HTML.)

Su Firefox 14.0.1 su un Mac, l'immagine di caricamento viene attivata se ridimensiono il browser a qualcosa di veramente grande e poi lo ridimensiono torna di nuovo a qualcosa di piccolo prima che l'immagine grande abbia la possibilità di caricarsi completamente. Finisce per segnalare "Immagine danneggiata o troncata" nella console di Firebug, ma non lancia un'eccezione o attiva un evento di errore. Nessuna indicazione c'è qualcosa di sbagliato nel codice. Solo nella console di Firebug. Nel frattempo, memorizza un'immagine troncata in localStorage.

Come posso rilevare in modo affidabile ed efficiente questo problema all'interno di JavaScript in modo da non memorizzare nella cache quell'immagine?

Ecco come lo scorrere il div picturefill per trovare i tag img che sono stati inseriti da 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); 
        } 
       } 
      } 
     } 
    } 

Ed ecco quello che la richiamata cacheImage() assomiglia:

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

Infine, qui è il testo completo di ciò che sto vedendo in Firebug con l'URL modificato per proteggere il colpevole:

Immagine corrotto o troncato: http://www.example.com/pf/external/imgs/extralarge.png

+2

Non attiva un evento 'error' sull'elemento' '? – MaxArt

+2

Ci si potrebbe chiedere perché stai cercando di implementare la memorizzazione nella cache delle immagini nella memoria locale invece di lasciare che la cache del browser faccia funzionare? – jfriend00

+0

@ jfriend00 Sto memorizzando l'immagine nella cache per l'utilizzo offline. L'ho detto nella domanda, ma l'ho espresso come un accenno. Ho modificato la domanda per dare maggiore enfasi al bit offline. Ad ogni modo, la prossima domanda ovvia è perché non utilizzare applaching offline HTML5. Per la spiegazione del motivo per cui le immagini reattive e la applaching offline HTML5 non sono compatibili, consultare http://www.alistapart.com/articles/application-cache-is-a-douchebag/ – Trott

risposta

9

Sembra che quando si cambia l'attributo src del tag img, Firefox spara un evento load. Ciò è contrario alle specifiche HTML5, che, se l'attributo src viene modificato, è necessario che says sostituisca qualsiasi altra raccolta già in corso (quale fa Firefox) e non si dovrebbero inviare eventi. L'evento load deve essere inviato solo se il recupero è stato completato correttamente. Quindi direi che il fatto di ottenere un evento load è un bug di Firefox.

Tuttavia, l'immagine dovrebbe sapere se è completamente disponibile o no, si potrebbe tentare di utilizzare l'attributo complete:

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

Purtroppo, Firefox ha this.complete insieme a true, invece, in modo che non è un opzione

L'opzione migliore potrebbe essere quella di creare un nuovo elemento <img> ogni volta che si desidera modificare l'attributo src.

+0

Sfortunatamente, this.complete è vero anche in quel momento, quindi questo non aggira il problema. Penso che quello che sta succedendo è che una volta che il set è impostato su vero, Firefox non lo imposta mai su false quando src è cambiato Harrumph, grazie per aver menzionato le specifiche HTML5, dovrò verificarlo, ho pensato che fosse ambiguo, ma se no, forse è il momento di presentare una bug! – Trott

+0

Infatti, l'ho provato io stesso ora e il flag 'complete' rimane' true', ed è di sola lettura, non può essere modificato manualmente. Quindi, aspetta Firefox per correggere questo bug, oppure puoi creare un nuovo elemento 'img' ogni volta che si cambia' src' e si sostituisce quello vecchio –

+0

In realtà, mentre provavo l'esempio, ho notato che non ricevevo un evento 'load' quando cambiava' src' e il l'immagine non è stata caricata completamente Testato su FF 14.0.1 su Linux, usando sia immagini png che jpg. Ho creato [questo jsfiddl e] (http://jsfiddle.net/GfKCf/5/) per provarlo, aprire Firebug e vedere quali eventi sono registrati nella console. –

2

Oggi sono rimasto interdetto da questo problema. Tutto funzionava perfettamente (le immagini venivano caricate visivamente come previsto), tranne che l'errore continuava a essere visualizzato nella console degli errori di Firefox, senza però errori di IE o di Chrome.

Nel mio caso stavo inserendo un'immagine in un div con innerHtml in un gestore jquery completo. Gli errori si fermarono quando mi anticipò la chiamata jquery con:

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

Ha funzionato per me, ma rende comunque non ha senso. Presumo che sia qualcosa che ha a che fare con il tempismo visto che questo codice avvia l'immagine da caricare prima che arrivi al codice che in realtà lo inserisce nella pagina.

+0

Questo lo ha risolto anche per me. Strano! –

Problemi correlati