web-dev-qa-db-fra.com

Iframe.readyState ne fonctionne pas dans chrome

Je crée un Iframe à la volée et définit comme URL une page qui télécharge un fichier binaire (xls, doc ...). Pendant le téléchargement des fichiers, je montre une animation. Quand non, je le cache.

Le problème est que Chrome ne sait pas quand les fichiers sont complètement téléchargés, c'est-à-dire lorsque l'iframe est complètement chargé. J'utilise la propriété iframe readyState pour vérifier l'état de l'iframe:

var iframe = document.createElement("iframe");
iframe.style.visibility = "hidden";
// I start a progress animation
window.setTimeout(showProgressAnimation, 1000);
// I start the file download
iframe.src ='GetFile.aspx?file=' + fileName;
document.body.appendChild(iframe);


function showProgressAnimation() {
   if (iframe.readyState == "complete" || iframe.readyState == "interactive") {
      // I stop the animation and show the page
      animation.style.display = 'none';
      progressBar.hide();
      $('#page').show();
   }
   else {
      // Chrome is always getting into this line
      window.setTimeout(showProgressAnimation, 1000);
   }
}

Le résultat est donc une boucle infinie.

J'ai essayé ce qui suit et cela fonctionne dans Firefox et Chrome mais pas lorsque le contenu est un fichier binaire:

if ($.browser.mozilla || $.browser.webkit ) {
    iframe.onload = function showProgressAnimation() {
        animation.style.display = 'none';
        progressBar.hide();
        $('#page').show();
    }
}
// IE
else{
     window.setTimeout(showProgressAnimation, 1000);
}
30
anmarti

Vous pouvez utiliser le onload pour signaler la charge du iframe

voici un exemple simple qui fonctionne

var iframe = document.createElement("iframe");
iframe.style.display = "none";
// this function will called when the iframe loaded
iframe.onload = function (){
  iframe.style.display = "block";    
  alert("loaded");
};
// set the src last.
iframe.src ='http://www.test.com';

// add it to the page.
document.getElementById("one").appendChild(iframe);

Testé ici:
http://jsfiddle.net/48MQW/5/
Avec src chargé en dernier.
http://jsfiddle.net/48MQW/24/

13
Aristos

Le contenu du fichier téléchargeable ne déclenche pas le gestionnaire d'événements readystatechange ou le gestionnaire d'événements onload. De cette façon, vous pouvez définir un cookie côté serveur ainsi que le contenu du fichier, et côté client vérifier régulièrement ce cookie. Par exemple:

serveur

response.cookie('fileDownloaded','true');
response.header('attachment','your-file-name.any');
//...write bytes to response...

client

var checker = setInterval(()=>{
    if(document.cookie.indexOf('fileDownloaded')>-1){
        alert('done');
        clearInterval(checker);
    }
},100);

Bien sûr, vous pouvez utiliser votre framework pour vérifier correctement la valeur du cookie, ce n'est qu'un poc, pas un analyseur de cookie sûr.

4
sarkiroka

Veuillez essayer ceci - vous mélangez vraiment dom et jQuery d'une ligne à l'autre

var tId;

function stopAnim() {
    // I stop the animation and show the page
    animation.hide();
    progressBar.hide();
    $('#page').show();
    clearInterval(tId);
}
var iframe = $("<iframe />");
iframe.css("visibility","hidden");

iframe.on("readystatechange",function() {
 if (this.readyState == "complete" || this.readyState == "interactive") {
   stopAnim();
 }
});
iframe.on("load",function() { // can possibly be deleted
 if (tId) {
   stopAnim();
 }
});

iframe.attr("src","GetFile.aspx?file=" + fileName);
$("body").append(iframe);
tId = setInterval(function() {
  // update progress here
}, 1000); // 
2
mplungjan