33 Stimmen

Iframe.readyState funktioniert nicht in Chrome

Ich erstelle ein Iframe und setze dynamisch die URL einer Seite, die eine Binärdatei (xls, doc...) herunterlädt. Während die Dateien heruntergeladen werden, zeige ich eine Animation. Wenn dies nicht der Fall ist, verstecke ich sie.

Das Problem ist, dass Chrome nicht weiß, wann die Dateien vollständig heruntergeladen sind, also wenn das Iframe vollständig geladen ist. Ich benutze die Iframe-Eigenschaft readyState, um den Status des Iframes zu überprüfen:

var iframe = document.createElement("iframe");
iframe.style.visibility = "hidden;
// Ich starte eine Fortschrittsanimation
window.setTimeout(showProgressAnimation, 1000);
// Ich starte den Dateidownload
iframe.src ='GetFile.aspx?file=' + fileName;
document.body.appendChild(iframe);

function showProgressAnimation() {
   if (iframe.readyState == "complete" || iframe.readyState == "interactive") {
      // Ich stoppe die Animation und zeige die Seite
      animation.style.display = 'none';
      progressBar.hide();
      $('#page').show();
   }
   else {
      // Chrome gelangt immer zu dieser Zeile
      window.setTimeout(showProgressAnimation, 1000);
   }
}

Das Ergebnis ist also eine Endlosschleife.

Ich habe Folgendes versucht und es funktioniert in Firefox und Chrome nicht, wenn der Inhalt eine Binärdatei ist:

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

16voto

Aristos Punkte 64742

Sie können das onload verwenden, um das Laden des iframe zu signalisieren

hier ist ein einfaches Beispiel, das funktioniert

var iframe = document.createElement("iframe");
iframe.style.display = "none";
// Diese Funktion wird aufgerufen, wenn das iframe geladen wurde
iframe.onload = function (){
  iframe.style.display = "block";    
  alert("geladen");
};
// Setzen Sie zuletzt die src.
iframe.src ='http://www.test.com';

// Fügen Sie es der Seite hinzu.
document.getElementById("one").appendChild(iframe);

Hier getestet:
http://jsfiddle.net/48MQW/5/
Mit src zuletzt geladen.
http://jsfiddle.net/48MQW/24/

6voto

sarkiroka Punkte 1380

Der herunterladbare Dateiinhalt löst nicht das readystatechange-Ereignishandler oder das onload-Ereignishandler aus. Dies führt dazu, dass Sie zusammen mit dem Dateiinhalt auf der Serverseite ein Cookie setzen können und auf der Clientseite dieses Cookie regelmäßig überprüfen können. Zum Beispiel:

Server

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('fertig');
        clearInterval(checker);
    }
},100);

Sie können natürlich Ihr Framework verwenden, um den Cookie-Wert korrekt zu überprüfen. Dies ist nur ein Prototyp, kein sicherer Cookie-Parser.

1voto

mplungjan Punkte 153338

Bitte versuchen Sie dies - Sie mischen wirklich dom und jQuery von Zeile zu Zeile

var tId;

function stopAnim() {
    // Ich stoppe die Animation und zeige die Seite
    animation.hide();
    progressBar.hide();
    $('#page').show();
    clearInterval(tId);
}
var iframe = $("");
iframe.css("visibility","hidden");

iframe.on("readystatechange",function() {
 if (this.readyState == "complete" || this.readyState == "interactive") {
   stopAnim();
 }
});
iframe.on("load",function() { // kann möglicherweise gelöscht werden
 if (tId) {
   stopAnim();
 }
});

iframe.attr("src","GetFile.aspx?file=" + fileName);
$("body").append(iframe);
tId = setInterval(function() {
  // Fortschritt hier aktualisieren
}, 1000); // 
</code></pre></x-turndown>

0voto

hexmark records Punkte 11

Sarkiroka's Lösung hat für mich funktioniert. Ich habe eine Instanz id zum Cookienamen hinzugefügt, um eine thread-sichere Lösung bereitzustellen:

const instanceId = "irgendeine UUID vom Client abgerufen";

response.cookie(`fileDownloaded-${instanceId}`,'true', { path: '/', secure: true, maxAge: 90000});
response.header('attachment','dein-dateiname.irgendwas');
//... Schreib Bytes in die Antwort ...

client

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

CodeJaeger.com

CodeJaeger ist eine Gemeinschaft für Programmierer, die täglich Hilfe erhalten..
Wir haben viele Inhalte, und Sie können auch Ihre eigenen Fragen stellen oder die Fragen anderer Leute lösen.

Powered by:

X