J'ai une page qui permet à l'utilisateur de télécharger un fichier généré dynamiquement. Cela prend beaucoup de temps à générer, je voudrais donc afficher un indicateur "d'attente". Le problème est que je ne sais pas comment détecter quand le navigateur a reçu le fichier, je peux donc masquer l'indicateur.
Je fais la demande sous une forme cachée, qui POSTE au serveur et cible une iframe cachée pour ses résultats. C'est ainsi que je ne remplace pas la totalité de la fenêtre du navigateur par le résultat. J'écoute un événement de "chargement" sur l'iframe, dans l'espoir qu'il se déclenche lorsque le téléchargement est terminé.
Je renvoie un en-tête "Content-Disposition: attachment" avec le fichier, ce qui fait que le navigateur affiche la boîte de dialogue "Enregistrer". Mais le navigateur ne déclenche pas un événement de "chargement" dans l'iframe.
Une approche que j'ai essayée utilise une réponse en plusieurs parties. Il enverrait donc un fichier HTML vide, ainsi que le fichier téléchargeable joint. Par exemple:
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
Cela fonctionne dans Firefox; il reçoit le fichier HTML vide, déclenche l'événement "charger", puis affiche la boîte de dialogue "Enregistrer" pour le fichier téléchargeable. Mais il échoue sur IE et Safari; IE déclenche l'événement "load" mais ne télécharge pas le fichier, et Safari télécharge le fichier (avec un nom et un type de contenu incorrects) et ne déclenche pas l'événement "load".
Une approche différente pourrait être de faire un appel pour démarrer la création du fichier, puis d'interroger le serveur jusqu'à ce qu'il soit prêt, puis de télécharger le fichier déjà créé. Mais je préfère éviter de créer des fichiers temporaires sur le serveur.
Quelqu'un a-t-il une meilleure idée?
la source
Réponses:
Une solution possible utilise JavaScript sur le client.
L'algorithme client:
L'algorithme du serveur:
Code source du client (JavaScript):
Exemple de code serveur (PHP):
Où:
la source
Une solution très simple (et boiteuse) sur une ligne consiste à utiliser l'
window.onblur()
événement pour fermer la boîte de dialogue de chargement. Bien sûr, si cela prend trop de temps et que l'utilisateur décide de faire autre chose (comme lire des e-mails), la boîte de dialogue de chargement se fermera.la source
onbeforeunload
Merci.vieux fil, je sais ...
mais ceux qui sont menés ici par google pourraient être intéressés par ma solution. c'est très simple, mais fiable. et il permet d'afficher de vrais messages de progression (et peut être facilement branché aux processus existants):
le script qui traite (mon problème était: récupérer des fichiers via http et les livrer sous forme de zip) écrit le statut dans la session.
l'état est interrogé et affiché toutes les secondes. c'est tout (ok, ce n'est pas le cas. vous devez vous occuper de beaucoup de détails [par exemple les téléchargements simultanés], mais c'est un bon point de départ ;-)).
la page de téléchargement:
getstatus.php
download.php
la source
.each()
pour les inscriptions aux événements. dis juste$('a.download').click()
setTimeout('getstatus()', 1000);
. Utilisez directement la fn:setTimeout(getstatus, 1000);
J'utilise ce qui suit pour télécharger des objets blob et révoquer l'URL de l'objet après le téléchargement. ça marche en chrome et firefox!
une fois la boîte de dialogue de téléchargement de fichier fermée, la fenêtre reprend son focus afin que l'événement focus soit déclenché.
la source
Sur la base de l'exemple d'Elmer, j'ai préparé ma propre solution. Une fois que les éléments ont cliqué avec la classe de téléchargement définie , il permet d'afficher un message personnalisé à l'écran. J'ai utilisé le déclencheur de focus pour masquer le message.
Javascript
HTML
Vous devez maintenant implémenter n'importe quel élément à télécharger:
ou
Après chaque téléchargement, vous verrez un message que votre rapport crée, veuillez patienter ...
la source
J'ai écrit une classe JavaScript simple qui implémente une technique similaire à celle décrite dans la réponse bulltorious . J'espère que cela peut être utile à quelqu'un ici. Le projet GitHub s'appelle response-monitor.js
Par défaut, il utilise spin.js comme indicateur d'attente, mais il fournit également un ensemble de rappels pour la mise en œuvre d'un indicateur personnalisé.
JQuery est pris en charge mais n'est pas requis.
Caractéristiques notables
Exemple d'utilisation
HTML
Client (JavaScript simple)
Client (JQuery)
Client avec rappels (JQuery)
Serveur (PHP)
Pour plus d'exemples, consultez le dossier d' exemples sur le référentiel.
la source
Je suis très en retard à la fête, mais je mettrai cela ici si quelqu'un d'autre souhaite connaître ma solution:
J'ai eu un vrai problème avec ce problème précis mais j'ai trouvé une solution viable en utilisant des iframes (je sais, je sais. C'est terrible mais ça marche pour un problème simple que j'ai eu)
J'avais une page html qui a lancé un script php distinct qui a généré le fichier puis l'a téléchargé. Sur la page html, j'ai utilisé le jquery suivant dans l'en-tête html (vous devrez également inclure une bibliothèque jquery):
Sur your_download_script.php, disposez des éléments suivants:
Pour décomposer cela, jquery lance d'abord votre script php dans un iframe. L'iframe est chargé une fois le fichier généré. Ensuite, jquery lance à nouveau le script avec une variable de demande indiquant au script de télécharger le fichier.
La raison pour laquelle vous ne pouvez pas effectuer le téléchargement et la génération de fichiers en une seule fois est due à la fonction php header (). Si vous utilisez header (), vous changez le script en autre chose qu'une page Web et jquery ne reconnaîtra jamais le script de téléchargement comme étant «chargé». Je sais que cela ne détecte pas nécessairement quand un navigateur reçoit un fichier, mais votre problème ressemblait au mien.
la source
Si vous diffusez un fichier que vous générez de manière dynamique et que vous avez également implémenté une bibliothèque de messagerie serveur-client en temps réel, vous pouvez alerter votre client assez facilement.
La bibliothèque de messagerie serveur à client que j'aime et que je recommande est Socket.io (via Node.js). Une fois que votre script de serveur a terminé de générer le fichier en cours de streaming pour le téléchargement, votre dernière ligne dans ce script peut émettre un message vers Socket.io qui envoie une notification au client. Sur le client, Socket.io écoute les messages entrants émis par le serveur et vous permet d'agir sur eux. L'avantage d'utiliser cette méthode par rapport aux autres est que vous êtes en mesure de détecter un «vrai» événement de fin une fois la diffusion terminée.
Par exemple, vous pouvez afficher votre indicateur d'occupation après avoir cliqué sur un lien de téléchargement, diffuser votre fichier, émettre un message vers Socket.io à partir du serveur dans la dernière ligne de votre script de streaming, écouter le client pour une notification, recevoir la notification et mettez à jour votre interface utilisateur en masquant l'indicateur occupé.
Je me rends compte que la plupart des gens qui lisent les réponses à cette question peuvent ne pas avoir ce type de configuration, mais j'ai utilisé cette solution exacte avec grand effet dans mes propres projets et cela fonctionne à merveille.
Socket.io est incroyablement facile à installer et à utiliser. Voir plus: http://socket.io/
la source
"Comment détecter quand le navigateur reçoit le téléchargement de fichiers?"
J'ai rencontré le même problème avec cette configuration:
struts 1.2.9
jquery-1.3.2.
jquery-ui-1.7.1.custom
IE 11
java 5
Ma solution avec un cookie:
- Côté client:
lors de la soumission de votre formulaire, appelez votre fonction javascript pour masquer votre page et charger votre spinner en attente
Ensuite, appelez une fonction qui vérifiera toutes les 500 ms si un cookie provient du serveur.
Si le cookie est trouvé, arrêtez de vérifier toutes les 500 ms, expirez le cookie et appelez votre fonction pour revenir à votre page et supprimer le spinner en attente ( removeWaitingSpinner () ). Il est important de faire expirer le cookie si vous souhaitez pouvoir télécharger à nouveau un autre fichier!
- Côté serveur:
à la fin de votre processus serveur, ajoutez un cookie à la réponse. Ce cookie sera envoyé au client lorsque votre fichier sera prêt à être téléchargé.
J'espère aider quelqu'un!
la source
Lorsque l'utilisateur déclenche la génération du fichier, vous pouvez simplement attribuer un ID unique à ce "téléchargement" et envoyer l'utilisateur vers une page qui se rafraîchit (ou vérifie avec AJAX) toutes les quelques secondes. Une fois le fichier terminé, enregistrez-le sous ce même ID unique et ...
Ensuite, vous pouvez ignorer tout le désordre iframe / attente / browserwindow, tout en ayant une solution vraiment élégante.
la source
Si vous ne souhaitez pas générer et stocker le fichier sur le serveur, êtes-vous prêt à stocker l'état, par exemple fichier en cours, fichier terminé? Votre page "en attente" pourrait interroger le serveur pour savoir quand la génération du fichier est terminée. Vous ne sauriez pas avec certitude si le navigateur a commencé le téléchargement, mais vous auriez une certaine confiance.
la source
Je viens d'avoir exactement le même problème. Ma solution était d'utiliser des fichiers temporaires car je générais déjà un tas de fichiers temporaires. Le formulaire est soumis avec:
À la fin du script qui génère le fichier, j'ai:
Cela entraînera le déclenchement de l'événement de chargement sur l'iframe. Ensuite, le message d'attente est fermé et le téléchargement du fichier démarre. Testé sur IE7 et Firefox.
la source
D'après mon expérience, il y a deux façons de gérer cela:
la source
Salutations, je sais que le sujet est ancien mais je laisse une solution que j'ai vue ailleurs et ça a marché:
Tu peux l'utiliser:
la source
Si vous avez téléchargé un fichier, qui est enregistré, par opposition à être dans le document, il n'y a aucun moyen de déterminer quand le téléchargement est terminé, car il n'est pas dans la portée du document actuel, mais un processus distinct dans le navigateur.
la source
La question est d'avoir un indicateur «d'attente» pendant la génération d'un fichier, puis de revenir à la normale une fois le fichier téléchargé. La façon dont j'aime faire cela consiste à utiliser un iFrame caché et à accrocher l'événement onload du cadre pour informer ma page lorsque le téléchargement démarre. MAIS onload ne se déclenche pas dans IE pour les téléchargements de fichiers (comme avec le jeton d'en-tête de pièce jointe). L'interrogation du serveur fonctionne, mais je n'aime pas la complexité supplémentaire. Voici donc ce que je fais:
Avertissement, ne faites pas cela sur un site très fréquenté, car la mise en cache pourrait s'additionner. Mais vraiment, si vos sites qui ont occupé le long processus vous affameront de toute façon.
Voici à quoi ressemble le codebehind, c'est tout ce dont vous avez vraiment besoin.
la source
Une solution rapide si vous souhaitez uniquement afficher un message ou un gif de chargeur jusqu'à ce que la boîte de dialogue de téléchargement s'affiche est de placer le message dans un conteneur caché et lorsque vous cliquez sur le bouton qui génère le fichier à télécharger, vous rendez le conteneur visible. Utilisez ensuite jquery ou javascript pour intercepter l'événement focusout du bouton pour masquer le conteneur qui contient le message
la source
Si Xmlhttprequest avec blob n'est pas une option, vous pouvez ouvrir votre fichier dans une nouvelle fenêtre et vérifier si les éléments eny sont remplis dans ce corps de fenêtre avec intervalle.
la source
Cet exemple Java / Spring détecte la fin d'un téléchargement, auquel cas il masque l'indicateur "Chargement ...".
Approche: Du côté JS, définissez un cookie avec un âge d'expiration maximal de 2 minutes et interrogez chaque seconde pour l' expiration des cookies . Ensuite, le côté serveur remplace ce cookie avec un âge d'expiration plus précoce - l'achèvement du processus serveur. Dès que l'expiration du cookie est détectée dans l'interrogation JS, "Loading ..." est masqué.
Côté JS
Côté serveur Java / Spring
la source
myCookie.setPath("/"); response.addCookie(myCookie);
Primefaces utilise également l'interrogation des cookies
https://github.com/primefaces/primefaces/blob/32bb00299d00e50b2cba430638468a4145f4edb0/src/main/resources/META-INF/resources/primefaces/core/core.js#L458
la source
Créez un iframe lorsque le bouton / lien est cliqué et ajoutez-le au corps.
Créez un iframe avec retard et supprimez-le après le téléchargement.
la source