Ich habe eine Seite, auf der der Benutzer eine dynamisch generierte Datei herunterladen kann. Das Generieren dauert lange, daher möchte ich einen "Warte" -Indikator anzeigen. Das Problem ist, dass ich nicht herausfinden kann, wie ich feststellen kann, wann der Browser die Datei empfangen hat, sodass ich den Indikator ausblenden kann.
Ich mache die Anfrage in einer versteckten Form, die an den Server POSTs und zielt auf einen versteckten Iframe für seine Ergebnisse. Dies ist so, dass ich nicht das gesamte Browserfenster durch das Ergebnis ersetze. Ich warte auf ein "Lade" -Ereignis im Iframe, in der Hoffnung, dass es ausgelöst wird, wenn der Download abgeschlossen ist.
Ich gebe einen "Content-Disposition: Anhang" -Header mit der Datei zurück, wodurch der Browser das Dialogfeld "Speichern" anzeigt. Der Browser löst jedoch kein "Lade" -Ereignis im Iframe aus.
Ein Ansatz, den ich ausprobiert habe, ist die Verwendung einer mehrteiligen Antwort. Es würde also eine leere HTML-Datei sowie die angehängte herunterladbare Datei senden. Zum Beispiel:
Content-type: multipart/x-mixed-replace;boundary="abcde"
--abcde
Content-type: text/html
--abcde
Content-type: application/vnd.fdf
Content-Disposition: attachment; filename=foo.fdf
file-content
--abcde
Dies funktioniert in Firefox. Es empfängt die leere HTML-Datei, löst das Ereignis "Laden" aus und zeigt dann das Dialogfeld "Speichern" für die herunterladbare Datei an. Aber es schlägt auf IE und Safari fehl; IE löst das Ereignis "Laden" aus, lädt die Datei jedoch nicht herunter, und Safari lädt die Datei herunter (mit dem falschen Namen und Inhaltstyp) und löst das Ereignis "Laden" nicht aus.
Ein anderer Ansatz könnte darin bestehen, einen Anruf zu tätigen, um die Dateierstellung zu starten, dann den Server abzufragen, bis er fertig ist, und dann die bereits erstellte Datei herunterzuladen. Ich möchte jedoch lieber vermeiden, temporäre Dateien auf dem Server zu erstellen.
Hat jemand eine bessere Idee?
quelle
Antworten:
Eine mögliche Lösung verwendet JavaScript auf dem Client.
Der Client-Algorithmus:
Der Server-Algorithmus:
Client-Quellcode (JavaScript):
Beispiel für einen Servercode (PHP):
Wo:
quelle
Eine sehr einfache (und lahme) einzeilige Lösung besteht darin, das
window.onblur()
Ereignis zum Schließen des Ladedialogs zu verwenden. Wenn es zu lange dauert und der Benutzer sich entscheidet, etwas anderes zu tun (z. B. E-Mails zu lesen), wird der Ladedialog natürlich geschlossen.quelle
onbeforeunload
Thank you ausgelöst wurde .alter Thread, ich weiß ...
Aber diejenigen, die hier von Google geführt werden, könnten an meiner Lösung interessiert sein. es ist sehr einfach und dennoch zuverlässig. und es ermöglicht die Anzeige von echten Fortschrittsmeldungen (und kann einfach in vorhandene Prozesse eingebunden werden):
Das Skript, das verarbeitet (mein Problem war: Dateien über http abrufen und als Zip-Datei bereitstellen), schreibt den Status in die Sitzung.
Der Status wird abgefragt und jede Sekunde angezeigt. das ist alles (ok, es ist nicht so. Sie müssen sich um viele Details kümmern [z. B. gleichzeitige Downloads], aber es ist ein guter Anfang ;-)).
die Downloadseite:
getstatus.php
download.php
quelle
.each()
für Event-Registrierungen verwenden. Sagen$('a.download').click()
setTimeout('getstatus()', 1000);
. Verwenden Sie die fn direkt:setTimeout(getstatus, 1000);
Ich benutze die folgenden, um Blobs herunterzuladen und die Objekt-URL nach dem Download zu widerrufen. es funktioniert in Chrom und Firefox!
Nachdem der Dialog zum Herunterladen von Dateien geschlossen wurde, erhält das Fenster ihren Fokus zurück, sodass das Fokusereignis ausgelöst wird.
quelle
Anhand von Elmers Beispiel habe ich meine eigene Lösung vorbereitet. Nachdem Elemente mit definierter Download- Klasse geklickt haben, können benutzerdefinierte Nachrichten auf dem Bildschirm angezeigt werden. Ich habe verwendet Fokus Trigger , um die Nachricht zu verbergen.
JavaScript
HTML
Jetzt sollten Sie jedes Element zum Herunterladen implementieren:
oder
Nach jedem Download- Klick sehen Sie eine Nachricht, die Ihr Bericht erstellt. Bitte warten Sie ...
quelle
Ich habe eine einfache JavaScript-Klasse geschrieben, die eine ähnliche Technik implementiert wie die in bulltorious answer beschriebene . Ich hoffe, es kann jemandem hier nützlich sein. Das GitHub-Projekt heißt response-monitor.js
Standardmäßig wird spin.js als Warteindikator verwendet, es werden jedoch auch Rückrufe für die Implementierung eines benutzerdefinierten Indikators bereitgestellt .
JQuery wird unterstützt, ist aber nicht erforderlich.
Bemerkenswerte Eigenschaften
Anwendungsbeispiel
HTML
Client (einfaches JavaScript)
Client (JQuery)
Client mit Rückrufen (JQuery)
Server (PHP)
Weitere Beispiele finden Sie im Beispielordner im Repository.
quelle
Ich bin sehr spät zur Party, aber ich werde das hier aufstellen, wenn jemand anderes meine Lösung wissen möchte:
Ich hatte einen echten Kampf mit genau diesem Problem, aber ich fand eine praktikable Lösung mit iframes (ich weiß, ich weiß. Es ist schrecklich, aber es funktioniert für ein einfaches Problem, das ich hatte)
Ich hatte eine HTML-Seite, die ein separates PHP-Skript startete, das die Datei generierte und dann herunterlud. Auf der HTML-Seite habe ich die folgende JQuery im HTML-Header verwendet (Sie müssen auch eine JQuery-Bibliothek einfügen):
Geben Sie in Ihrer_download_script.php Folgendes an:
Um dies zu beheben, startet jquery zuerst Ihr PHP-Skript in einem Iframe. Der Iframe wird geladen, sobald die Datei generiert wurde. Anschließend startet jquery das Skript erneut mit einer Anforderungsvariablen, die das Skript anweist, die Datei herunterzuladen.
Der Grund, warum Sie den Download und die Dateierzeugung nicht auf einmal durchführen können, liegt in der Funktion php header (). Wenn Sie header () verwenden, ändern Sie das Skript in eine andere als eine Webseite, und jquery erkennt das Download-Skript nie als "geladen". Ich weiß, dass dies möglicherweise nicht unbedingt erkennt, wenn ein Browser eine Datei empfängt, aber Ihr Problem klang ähnlich wie meins.
quelle
Wenn Sie eine Datei streamen, die Sie dynamisch generieren, und eine Echtzeit-Server-zu-Client-Messaging-Bibliothek implementiert ist, können Sie Ihren Client ganz einfach benachrichtigen.
Die Server-zu-Client-Messaging-Bibliothek, die ich mag und empfehle, ist Socket.io (über Node.js). Nachdem Ihr Serverskript fertig ist, kann die letzte Zeile in diesem Skript, die zum Herunterladen gestreamt wird, eine Nachricht an Socket.io senden, die eine Benachrichtigung an den Client sendet. Auf dem Client wartet Socket.io auf eingehende Nachrichten, die vom Server gesendet werden, und ermöglicht es Ihnen, darauf zu reagieren. Der Vorteil dieser Methode gegenüber anderen besteht darin, dass Sie nach Abschluss des Streamings ein "echtes" Endereignis erkennen können.
Sie können beispielsweise Ihre Besetztanzeige anzeigen, nachdem auf einen Download-Link geklickt wurde, Ihre Datei streamen, eine Nachricht vom Server in der letzten Zeile Ihres Streaming-Skripts an Socket.io senden, auf dem Client auf eine Benachrichtigung warten und die Benachrichtigung erhalten und aktualisieren Sie Ihre Benutzeroberfläche, indem Sie die Besetztanzeige ausblenden.
Mir ist klar, dass die meisten Leute, die Antworten auf diese Frage lesen, möglicherweise nicht über diese Art von Setup verfügen, aber ich habe diese exakte Lösung in meinen eigenen Projekten mit großer Wirkung verwendet und sie funktioniert wunderbar.
Socket.io ist unglaublich einfach zu installieren und zu verwenden. Weitere Informationen : http://socket.io/
quelle
"Wie erkennt man, wann der Browser den Dateidownload erhält?"
Ich hatte das gleiche Problem mit dieser Konfiguration:
struts
1.2.9 jquery-1.3.2.
jquery-ui-1.7.1.custom
IE 11
java 5
Meine Lösung mit einem Cookie:
- Client-Seite:
Rufen Sie beim Absenden Ihres Formulars Ihre Javascript-Funktion auf, um Ihre Seite auszublenden und Ihren wartenden Spinner zu laden
Rufen Sie dann eine Funktion auf, die alle 500 ms überprüft, ob ein Cookie vom Server kommt.
Wenn das Cookie gefunden wird, beenden Sie die Überprüfung alle 500 ms, lassen Sie das Cookie ablaufen und rufen Sie Ihre Funktion auf, um zu Ihrer Seite zurückzukehren und den wartenden Spinner zu entfernen ( removeWaitingSpinner () ). Es ist wichtig, das Cookie abzulaufen, wenn Sie eine andere Datei erneut herunterladen möchten!
- Serverseite:
Fügen Sie am Ende Ihres Serverprozesses der Antwort ein Cookie hinzu. Dieses Cookie wird an den Client gesendet, wenn Ihre Datei zum Download bereitsteht.
Ich hoffe jemandem zu helfen!
quelle
Wenn der Benutzer die Generierung der Datei auslöst, können Sie diesem "Download" einfach eine eindeutige ID zuweisen und den Benutzer an eine Seite senden, die alle paar Sekunden aktualisiert (oder mit AJAX überprüft) wird. Wenn die Datei fertig ist, speichern Sie sie unter derselben eindeutigen ID und ...
Dann können Sie das ganze Iframe / Warten / Browserfenster-Durcheinander überspringen und haben dennoch eine wirklich elegante Lösung.
quelle
Wenn Sie die Datei nicht generieren und auf dem Server speichern möchten, sind Sie bereit, den Status zu speichern, z. B. Datei in Bearbeitung, Datei vollständig? Ihre "wartende" Seite könnte den Server abfragen, um zu erfahren, wann die Dateierzeugung abgeschlossen ist. Sie würden nicht sicher wissen, ob der Browser den Download gestartet hat, aber Sie hätten ein gewisses Vertrauen.
quelle
Ich hatte gerade genau das gleiche Problem. Meine Lösung bestand darin, temporäre Dateien zu verwenden, da ich bereits eine Reihe temporärer Dateien generiert habe. Das Formular wird eingereicht mit:
Am Ende des Skripts, das die Datei generiert, habe ich:
Dadurch wird das Ladeereignis auf dem Iframe ausgelöst. Dann wird die Wartemeldung geschlossen und der Dateidownload gestartet. Getestet auf IE7 und Firefox.
quelle
Nach meiner Erfahrung gibt es zwei Möglichkeiten, damit umzugehen:
quelle
Grüße, ich weiß, dass das Thema alt ist, aber ich hinterlasse eine Lösung, die ich woanders gesehen habe und die funktioniert hat:
Du kannst es benutzen:
quelle
Wenn Sie eine Datei heruntergeladen haben, die gespeichert wird, anstatt sich im Dokument zu befinden, können Sie nicht feststellen, wann der Download abgeschlossen ist, da dies nicht im Umfang des aktuellen Dokuments liegt, sondern ein separater Vorgang im Browser.
quelle
Die Frage ist, ob beim Generieren einer Datei eine Warteanzeige angezeigt wird und nach dem Herunterladen der Datei wieder normal angezeigt wird. Ich verwende dazu gerne einen versteckten iFrame und verknüpfe das Onload-Ereignis des Frames, um meine Seite über den Start des Downloads zu informieren. ABER Onload wird im IE nicht für Dateidownloads ausgelöst (wie beim Header-Token für Anhänge). Das Abrufen des Servers funktioniert, aber ich mag die zusätzliche Komplexität nicht. Also hier ist was ich tue:
Haftungsausschluss, tun Sie dies nicht auf einer belebten Site, da sich das Caching summieren könnte. Aber wirklich, wenn Ihre Websites, die den lang laufenden Prozess beschäftigt sind, Sie sowieso von Threads hungern lassen.
So sieht der Code aus, das ist alles, was Sie wirklich brauchen.
quelle
Eine schnelle Lösung, wenn Sie nur eine Nachricht oder ein Loader-GIF anzeigen möchten, bis der Download-Dialog angezeigt wird, besteht darin, die Nachricht in einem versteckten Container abzulegen. Wenn Sie auf die Schaltfläche klicken, mit der die herunterzuladende Datei generiert wird, wird der Container sichtbar. Verwenden Sie dann jquery oder javascript, um das Focusout-Ereignis der Schaltfläche abzufangen und den Container auszublenden, der die Nachricht enthält
quelle
Wenn Xmlhttprequest mit Blob keine Option ist, können Sie Ihre Datei in einem neuen Fenster öffnen und prüfen, ob in diesem Fensterkörper eny Elemente mit Intervallen ausgefüllt werden.
quelle
In diesem Java / Spring-Beispiel wird das Ende eines Downloads erkannt. An diesem Punkt wird die Anzeige "Laden ..." ausgeblendet.
Vorgehensweise: Setzen Sie auf der JS-Seite ein Cookie mit einem maximalen Ablaufalter von 2 Minuten und fragen Sie jede Sekunde nach dem Ablaufdatum des Cookies . Dann überschreibt die Serverseite dieses Cookie mit einem früheren Ablaufalter - dem Abschluss des Serverprozesses. Sobald der Cookie-Ablauf in der JS-Abfrage erkannt wird, wird "Laden ..." ausgeblendet.
JS Seite
Java / Spring Server Seite
quelle
myCookie.setPath("/"); response.addCookie(myCookie);
Primefaces verwendet auch Cookie-Polling
https://github.com/primefaces/primefaces/blob/32bb00299d00e50b2cba430638468a4145f4edb0/src/main/resources/META-INF/resources/primefaces/core/core.js#L458
quelle
Erstellen Sie einen Iframe, wenn Sie auf die Schaltfläche / den Link klicken, und hängen Sie diesen an den Text an.
Erstellen Sie einen Iframe mit Verzögerung und löschen Sie ihn nach dem Download.
quelle