web-dev-qa-db-fra.com

Détecter quand le navigateur reçoit le téléchargement du fichier

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, donc j'aimerais 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, ce qui me permet de cacher l'indicateur.

Je fais la demande sous une forme cachée, qui est postée sur le serveur et qui cible un iframe caché pour obtenir ses résultats. C'est pour que je ne remplace pas la fenêtre entière du navigateur avec le résultat. J'écoute un événement "load" sur l'iframe, dans l'espoir qu'il se déclenche une fois le téléchargement terminé.

Je retourne un en-tête "Content-Disposition: attachment" avec le fichier, ce qui amène le navigateur à afficher la boîte de dialogue "Enregistrer". Mais le navigateur ne déclenche pas un événement "load" dans l'iframe.

Une approche que j'ai essayée utilise une réponse en plusieurs parties. Donc, il enverrait 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 "load", puis affiche la boîte de dialogue "Enregistrer" du 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. 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 interroger le serveur jusqu'à ce qu'il soit prêt, puis 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?

452
JW.

One solution possible utilise JavaScript sur le client.

L'algorithme client:

  1. Générez un jeton unique aléatoire.
  2. Soumettez la demande de téléchargement et incluez le jeton dans un champ GET/POST.
  3. Affiche l'indicateur "En attente".
  4. Démarrez un chronomètre et, toutes les secondes environ, recherchez un cookie nommé "fileDownloadToken" (ou ce que vous décidez).
  5. Si le cookie existe et que sa valeur correspond au jeton, masquez l'indicateur "En attente".

L'algorithme du serveur:

  1. Recherchez le champ GET/POST dans la demande.
  2. Si la valeur n'est pas vide, supprimez un cookie (par exemple, "fileDownloadToken") et définissez sa valeur sur celle du jeton.

Code source du client (JavaScript):

function getCookie( name ) {
  var parts = document.cookie.split(name + "=");
  if (parts.length == 2) return parts.pop().split(";").shift();
}

function expireCookie( cName ) {
    document.cookie = 
        encodeURIComponent(cName) + "=deleted; expires=" + new Date( 0 ).toUTCString();
}

function setCursor( docStyle, buttonStyle ) {
    document.getElementById( "doc" ).style.cursor = docStyle;
    document.getElementById( "button-id" ).style.cursor = buttonStyle;
}

function setFormToken() {
    var downloadToken = new Date().getTime();
    document.getElementById( "downloadToken" ).value = downloadToken;
    return downloadToken;
}

var downloadTimer;
var attempts = 30;

// Prevents double-submits by waiting for a cookie from the server.
function blockResubmit() {
    var downloadToken = setFormToken();
    setCursor( "wait", "wait" );

    downloadTimer = window.setInterval( function() {
        var token = getCookie( "downloadToken" );

        if( (token == downloadToken) || (attempts == 0) ) {
            unblockSubmit();
        }

        attempts--;
    }, 1000 );
}

function unblockSubmit() {
  setCursor( "auto", "pointer" );
  window.clearInterval( downloadTimer );
  expireCookie( "downloadToken" );
  attempts = 30;
}

Exemple de code serveur (PHP):

$TOKEN = "downloadToken";

// Sets a cookie so that when the download begins the browser can
// unblock the submit button (thus helping to prevent multiple clicks).
// The false parameter allows the cookie to be exposed to JavaScript.
$this->setCookieToken( $TOKEN, $_GET[ $TOKEN ], false );

$result = $this->sendFile();

Où:

public function setCookieToken(
    $cookieName, $cookieValue, $httpOnly = true, $secure = false ) {

    // See: http://stackoverflow.com/a/1459794/59087
    // See: http://shiflett.org/blog/2006/mar/server-name-versus-http-Host
    // See: http://stackoverflow.com/a/3290474/59087
    setcookie(
        $cookieName,
        $cookieValue,
        2147483647,            // expires January 1, 2038
        "/",                   // your path
        $_SERVER["HTTP_Host"], // your domain
        $secure,               // Use true over HTTPS
        $httpOnly              // Set true for $AUTH_COOKIE_NAME
    );
}
422
bulltorious

Une solution très simple (et boiteuse) sur une ligne consiste à utiliser l'événement window.onblur() 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 courriels), la boîte de dialogue de chargement se ferme.

27
birdman

vieux fil, je sais ...

mais ceux qui sont dirigés ici par Google pourraient être intéressés par ma solution. c'est très simple, mais fiable. et cela permet d'afficher des messages de progression réels (et peut être facilement connecté aux processus existants):

le script qui traite (mon problème était: récupérer des fichiers via http et les transmettre au format Zip) écrit le statut dans la session.

l'état est scruté et affiché toutes les secondes. c'est tout (d'accord, ce n'est pas le cas. vous devez vous occuper de nombreux 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:

    <a href="download.php?id=1" class="download">DOWNLOAD 1</a>
    <a href="download.php?id=2" class="download">DOWNLOAD 2</a>
    ...
    <div id="wait">
    Please wait...
    <div id="statusmessage"></div>
    </div>
    <script>
//this is jquery
    $('a.download').each(function()
       {
        $(this).click(
             function(){
               $('#statusmessage').html('prepare loading...');
               $('#wait').show();
               setTimeout('getstatus()', 1000);
             }
          );
        });
    });
    function getstatus(){
      $.ajax({
          url: "/getstatus.php",
          type: "POST",
          dataType: 'json',
          success: function(data) {
            $('#statusmessage').html(data.message);
            if(data.status=="pending")
              setTimeout('getstatus()', 1000);
            else
              $('#wait').hide();
          }
      });
    }
    </script>

getstatus.php

<?php
session_start();
echo json_encode($_SESSION['downloadstatus']);
?>

download.php

    <?php
    session_start();
    $processing=true;
    while($processing){
      $_SESSION['downloadstatus']=array("status"=>"pending","message"=>"Processing".$someinfo);
      session_write_close();
      $processing=do_what_has_2Bdone();
      session_start();
    }
      $_SESSION['downloadstatus']=array("status"=>"finished","message"=>"Done");
//and spit the generated file to the browser
    ?>
12
bytepirate

j'utilise ce qui suit pour télécharger des blobs et révoquer l'objet-url après le téléchargement. cela fonctionne dans chrome et firefox!

function download(blob){
    var url = URL.createObjectURL(blob);
    console.log('create ' + url);

    window.addEventListener('focus', window_focus, false);
    function window_focus(){
        window.removeEventListener('focus', window_focus, false);                   
        URL.revokeObjectURL(url);
        console.log('revoke ' + url);
    }
    location.href = url;
}

une fois la boîte de dialogue de téléchargement de fichier fermée, la fenêtre récupère son focus et l’événement de focus est déclenché.

10
Elmer

J'ai écrit une classe JavaScript simple qui implémente une technique similaire à celle décrite dans bulltorious answer . J'espère que cela pourra ê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 l’implémentation d’un indicateur personnalisé.

JQuery est pris en charge mais pas obligatoire.

Caractéristiques notables

  • Intégration simple
  • Pas de dépendances
  • Plug-in JQuery (facultatif)
  • Intégration de Spin.js (facultatif)
  • Rappels configurables pour la surveillance des événements
  • Traite plusieurs demandes simultanées
  • Détection d'erreur côté serveur
  • Détection de délai
  • Navigateur croisé

Exemple d'utilisation

HTML

<!-- the response monitor implementation -->
<script src="response-monitor.js"></script>

<!-- optional JQuery plug-in -->
<script src="response-monitor.jquery.js"></script> 

<a class="my_anchors" href="/report?criteria1=a&criteria2=b#30">Link 1 (Timeout: 30s)</a>
<a class="my_anchors" href="/report?criteria1=b&criteria2=d#10">Link 2 (Timeout: 10s)</a>

<form id="my_form" method="POST">
    <input type="text" name="criteria1">
    <input type="text" name="criteria2">
    <input type="submit" value="Download Report">
</form>

Client (JavaScript simple)

//registering multiple anchors at once
var my_anchors = document.getElementsByClassName('my_anchors');
ResponseMonitor.register(my_anchors); //clicking on the links initiates monitoring

//registering a single form
var my_form = document.getElementById('my_form');
ResponseMonitor.register(my_form); //the submit event will be intercepted and monitored

Client (JQuery)

$('.my_anchors').ResponseMonitor();
$('#my_form').ResponseMonitor({timeout: 20});

Client avec rappel (JQuery)

//when options are defined, the default spin.js integration is bypassed
var options = {
    onRequest: function(token){
        $('#cookie').html(token);
        $('#outcome').html('');
        $('#duration').html(''); 
    },
    onMonitor: function(countdown){
        $('#duration').html(countdown); 
    },
    onResponse: function(status){
        $('#outcome').html(status==1?'success':'failure');
    },
    onTimeout: function(){
        $('#outcome').html('timeout');
    }
};

//monitor all anchors in the document
$('a').ResponseMonitor(options);

Serveur (PHP)

$cookiePrefix = 'response-monitor'; //must match the one set on the client options
$tokenValue = $_GET[$cookiePrefix];
$cookieName = $cookiePrefix.'_'.$tokenValue; //ex: response-monitor_1419642741528

//this value is passed to the client through the ResponseMonitor.onResponse callback
$cookieValue = 1; //for ex, "1" can interpret as success and "0" as failure

setcookie(
    $cookieName,
    $cookieValue,
    time()+300,            // expire in 5 minutes
    "/",
    $_SERVER["HTTP_Host"],
    true,
    false
);

header('Content-Type: text/plain');
header("Content-Disposition: attachment; filename=\"Response.txt\"");

sleep(5); //simulate whatever delays the response
print_r($_REQUEST); //dump the request in the text file

Pour plus d'exemples, consultez le dossier examples dans le référentiel.

8
Jorge Paulo

Si vous diffusez de manière dynamique un fichier que vous générez 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 recommande est Socket.io (via Node.js). Une fois que le script de votre serveur est terminé, le fichier en cours de lecture en vue du téléchargement peut envoyer un message à 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 en conséquence. L'avantage d'utiliser cette méthode par rapport aux autres est que vous pouvez détecter un "vrai" événement de fin une fois le streaming terminé.

Par exemple, vous pouvez afficher votre indicateur occupé après avoir cliqué sur un lien de téléchargement, diffuser votre fichier en streaming, émettre un message à Socket.io à partir du serveur situé sur la dernière ligne de votre script de streaming, écouter une notification sur le client, 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 n’ont peut-être pas ce type de configuration, mais j’utilise cette solution avec beaucoup d’efficacité dans mes propres projets et cela fonctionne à merveille.

Socket.io est incroyablement facile à installer et à utiliser. Voir plus: http://socket.io/

5
Art Geigel

Sur la base de l'exemple d'Elmer, j'ai préparé ma propre solution. Après que les éléments aient cliqué avec la classe définie download , il permet d'afficher un message personnalisé à l'écran. J'ai utilisé le déclencheur de focus pour masquer le message.

JavaScript

$(function(){$('.download').click(function() { ShowDownloadMessage(); }); })

function ShowDownloadMessage()
{
     $('#message-text').text('your report is creating, please wait...');
     $('#message').show();
     window.addEventListener('focus', HideDownloadMessage, false);
}

function HideDownloadMessage(){
    window.removeEventListener('focus', HideDownloadMessage, false);                   
    $('#message').hide();
}

HTML

<div id="message" style="display: none">
    <div id="message-screen-mask" class="ui-widget-overlay ui-front"></div>
    <div id="message-text" class="ui-dialog ui-widget ui-widget-content ui-corner-all ui-front ui-draggable ui-resizable waitmessage">please wait...</div>
</div>

Maintenant vous devez implémenter n'importe quel élément à télécharger:

<a class="download" href="file://www.ocelot.com.pl/prepare-report">Download report</a>

ou

<input class="download" type="submit" value="Download" name="actionType">

Après chaque téléchargement , vous verrez le message votre rapport est en cours de création, veuillez patienter ...

5
Jerzy Gebler

Je suis très tard pour la fête, mais je vais mettre ceci ici si quelqu'un d'autre veut connaître ma solution:

J'ai eu un réel problème avec ce problème, mais j'ai trouvé une solution viable en utilisant des iframes (je sais, je sais. C'est terrible, mais cela fonctionne pour un problème simple que j'avais).

J'ai eu une page html qui a lancé un script php distinct qui a généré le fichier et l'a ensuite 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):

<script>
    $(function(){
        var iframe = $("<iframe>", {name: 'iframe', id: 'iframe',}).appendTo("body").hide();
        $('#click').on('click', function(){
            $('#iframe').attr('src', 'your_download_script.php');
        });
        $('iframe').load(function(){
            $('#iframe').attr('src', 'your_download_script.php?download=yes'); <!--on first iframe load, run script again but download file instead-->
            $('#iframe').unbind(); <!--unbinds the iframe. Helps prevent against infinite recursion if the script returns valid html (such as echoing out exceptions) -->
        });
    });
</script>

Sur your_download_script.php, procédez comme suit:

function downloadFile($file_path) {
    if (file_exists($file_path)) {
        header('Content-Description: File Transfer');
        header('Content-Type: text/csv');
        header('Content-Disposition: attachment; filename=' . basename($file_path));
        header('Expires: 0');
        header('Cache-Control: must-revalidate');
        header('Pragma: public');
        header('Content-Length: ' . filesize($file_path));
        ob_clean();
        flush();
        readfile($file_path);
        exit();
    }
}


$_SESSION['your_file'] = path_to_file; //this is just how I chose to store the filepath

if (isset($_REQUEST['download']) && $_REQUEST['download'] == 'yes') {
    downloadFile($_SESSION['your_file']);
} else {
    *execute logic to create the file*
}

Pour décomposer cela, jquery commence par lancer votre script php dans une iframe. L'iframe est chargé une fois le fichier généré. Ensuite jquery lance à nouveau le script avec une variable de requête lui demandant de télécharger le fichier.

La raison pour laquelle vous ne pouvez pas faire le téléchargement et la génération de fichiers en une fois est due à la fonction php header (). Si vous utilisez header (), vous remplacez le script par 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 peut-être pas nécessairement quand un navigateur reçoit un fichier, mais votre problème semblait similaire au mien.

3
Walker Boh

Lorsque l'utilisateur déclenche la génération du fichier, vous pouvez simplement attribuer un identifiant unique à ce "téléchargement" et lui envoyer une page qui s'actualise (ou vérifie avec AJAX) toutes les quelques secondes. Une fois le fichier terminé, enregistrez-le sous le même identifiant unique et ...

  • Si le fichier est prêt, effectuez le téléchargement.
  • Si le fichier n'est pas prêt, affichez la progression.

Ensuite, vous pouvez ignorer tout le désordre iframe/waiting/browserwindow tout en ayant une solution vraiment élégante.

3
gahooa

Si vous ne souhaitez pas générer et stocker le fichier sur le serveur, acceptez-vous de stocker le statut, par exemple fichier en cours, fichier complet? Votre page "attente" pourrait interroger le serveur pour savoir quand la génération du fichier est terminée. Vous ne sauriez pas avec certitude que le navigateur a commencé le téléchargement, mais vous auriez une certaine confiance.

3
bmb

Je viens d'avoir exactement le même problème. Ma solution consistait à utiliser des fichiers temporaires, car je générais déjà un tas de fichiers temporaires. Le formulaire est soumis avec:

var microBox = {
    show : function(content) {
        $(document.body).append('<div id="microBox_overlay"></div><div id="microBox_window"><div id="microBox_frame"><div id="microBox">' +
        content + '</div></div></div>');
        return $('#microBox_overlay');
    },

    close : function() {
        $('#microBox_overlay').remove();
        $('#microBox_window').remove();
    }
};

$.fn.bgForm = function(content, callback) {
    // Create an iframe as target of form submit
    var id = 'bgForm' + (new Date().getTime());
    var $iframe = $('<iframe id="' + id + '" name="' + id + '" style="display: none;" src="about:blank"></iframe>')
        .appendTo(document.body);
    var $form = this;
    // Submittal to an iframe target prevents page refresh
    $form.attr('target', id);
    // The first load event is called when about:blank is loaded
    $iframe.one('load', function() {
        // Attach listener to load events that occur after successful form submittal
        $iframe.load(function() {
            microBox.close();
            if (typeof(callback) == 'function') {
                var iframe = $iframe[0];
                var doc = iframe.contentWindow.document;
                var data = doc.body.innerHTML;
                callback(data);
            }
        });
    });

    this.submit(function() {
        microBox.show(content);
    });

    return this;
};

$('#myForm').bgForm('Please wait...');

A la fin du script qui génère le fichier, j'ai:

header('Refresh: 0;url=fetch.php?token=' . $token);
echo '<html></html>';

Cela provoquera 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 commence. Testé sur IE7 et Firefox.

2
grom

Si vous avez téléchargé un fichier, qui est enregistré, par opposition à celui du document, il n’ya aucun moyen de déterminer à quel moment le téléchargement est terminé, car il n’appartient pas à la portée du document actuel, mais à un processus distinct dans le navigateur.

"Comment détecter quand un navigateur reçoit un téléchargement de fichier?"
J'ai rencontré le même problème avec cette configuration:
entretoises 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:
Lorsque vous soumettez votre formulaire, appelez votre fonction javascript pour masquer votre page et charger votre spinner en attente.

function loadWaitingSpinner(){
... hide your page and show your spinner ...
}

Ensuite, appelez une fonction qui vérifiera toutes les 500 ms si un cookie provient du serveur.

function checkCookie(){
    var verif = setInterval(isWaitingCookie,500,verif);
}

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 que le cookie expire si vous voulez pouvoir télécharger à nouveau un autre fichier!

function isWaitingCookie(verif){
    var loadState = getCookie("waitingCookie");
    if (loadState == "done"){
        clearInterval(verif);
        document.cookie = "attenteCookie=done; expires=Tue, 31 Dec 1985 21:00:00 UTC;";
        removeWaitingSpinner();
    }
}
    function getCookie(cookieName){
        var name = cookieName + "=";
        var cookies = document.cookie
        var cs = cookies.split(';');
        for (var i = 0; i < cs.length; i++){
            var c = cs[i];
            while(c.charAt(0) == ' ') {
                c = c.substring(1);
            }
            if (c.indexOf(name) == 0){
                return c.substring(name.length, c.length);
            }
        }
        return "";
    }
function removeWaitingSpinner(){
... come back to your page and remove your spinner ...
}

- Côté serveur:
À la fin du processus de votre serveur, ajoutez un cookie à la réponse. Ce cookie sera envoyé au client lorsque votre fichier sera prêt pour le téléchargement.

Cookie waitCookie = new Cookie("waitingCookie", "done");
response.addCookie(waitCookie);

J'espère aider quelqu'un!

1
MB33

Une solution rapide si vous souhaitez uniquement afficher un message ou un gif de chargeur jusqu'à l'affichage de la boîte de dialogue de téléchargement consiste à placer le message dans un conteneur masqué. 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 capturer l'événement focusout du bouton afin de masquer le conteneur contenant le message.

0
Mihaela Rada

La question est d’avoir un indicateur "en attente" pendant la génération du fichier, puis de revenir à la normale une fois le fichier téléchargé. J'aime le faire en utilisant un iFrame caché et en reliant l'événement onload du cadre pour permettre à ma page de savoir quand le téléchargement commence. 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. Alors voici ce que je fais:

  • Ciblez l'iFrame caché comme d'habitude.
  • Générez le contenu. Cachez-le avec un délai d'expiration absolu en 2 minutes.
  • Envoyez une redirection javascript au client appelant, en appelant une seconde fois la page du générateur. REMARQUE: l'événement onload sera déclenché dans IE car il agit comme une page normale.
  • Supprimez le contenu du cache et envoyez-le au client.

Déni de responsabilité, ne le faites pas sur un site occupé, car la mise en cache pourrait s’ajouter. Mais vraiment, si vos sites qui occupent le long processus vont de toute façon vous priver de threads.

Voici à quoi ressemble le code ci-dessous, qui est tout ce dont vous avez vraiment besoin.

public partial class Download : System.Web.UI.Page
{
    protected System.Web.UI.HtmlControls.HtmlControl Body;

    protected void Page_Load( object sender, EventArgs e )
    {
        byte[ ] data;
        string reportKey = Session.SessionID + "_Report";

        // Check is this page request to generate the content
        //    or return the content (data query string defined)
        if ( Request.QueryString[ "data" ] != null )
        {
            // Get the data and remove the cache
            data = Cache[ reportKey ] as byte[ ];
            Cache.Remove( reportKey );

            if ( data == null )                    
                // send the user some information
                Response.Write( "Javascript to tell user there was a problem." );                    
            else
            {
                Response.CacheControl = "no-cache";
                Response.AppendHeader( "Pragma", "no-cache" );
                Response.Buffer = true;

                Response.AppendHeader( "content-disposition", "attachment; filename=Report.pdf" );
                Response.AppendHeader( "content-size", data.Length.ToString( ) );
                Response.BinaryWrite( data );
            }
            Response.End();                
        }
        else
        {
            // Generate the data here. I am loading a file just for an example
            using ( System.IO.FileStream stream = new System.IO.FileStream( @"C:\1.pdf", System.IO.FileMode.Open ) )
                using ( System.IO.BinaryReader reader = new System.IO.BinaryReader( stream ) )
                {
                    data = new byte[ reader.BaseStream.Length ];
                    reader.Read( data, 0, data.Length );
                }

            // Store the content for retrieval              
            Cache.Insert( reportKey, data, null, DateTime.Now.AddMinutes( 5 ), TimeSpan.Zero );

            // This is the key bit that tells the frame to reload this page 
            //   and start downloading the content. NOTE: Url has a query string 
            //   value, so that the content isn't generated again.
            Body.Attributes.Add("onload", "window.location = 'binary.aspx?data=t'");
        }
    }
0
MarcLawrence

Si Xmlhttprequest with 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 renseignés dans ce corps de fenêtre avec intervalle.

var form = document.getElementById("frmDownlaod");
 form.setAttribute("action","downoad/url");
 form.setAttribute("target","downlaod");
 var exportwindow = window.open("", "downlaod", "width=800,height=600,resizable=yes");
 form.submit();

var responseInterval = setInterval(function(){
        var winBody = exportwindow.document.body
        if(winBody.hasChildNodes()) // or 'downoad/url' === exportwindow.document.location.href
        {
                clearInterval(responseInterval);
                // do your work
                // if there is error page configured your application for failed requests, check for those dom elemets 
        }
}, 1000)
//Better if you specify maximun no of intervals
0
aniketKumkar