IdentifiantMot de passe
Loading...
Mot de passe oublié ?Je m'inscris ! (gratuit)
Navigation

Inscrivez-vous gratuitement
pour pouvoir participer, suivre les réponses en temps réel, voter pour les messages, poser vos propres questions et recevoir la newsletter

JavaScript Discussion :

[JSON][Tapestry] Téléchargement de fichier


Sujet :

JavaScript

  1. #1
    Membre éprouvé Avatar de leminipouce
    Homme Profil pro
    Ingénieur développement logiciels
    Inscrit en
    Janvier 2004
    Messages
    754
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 39
    Localisation : France, Haute Garonne (Midi Pyrénées)

    Informations professionnelles :
    Activité : Ingénieur développement logiciels
    Secteur : Agroalimentaire - Agriculture

    Informations forums :
    Inscription : Janvier 2004
    Messages : 754
    Points : 1 253
    Points
    1 253
    Par défaut [JSON][Tapestry] Téléchargement de fichier
    Bonjour tout le monde,

    J'ai une API Java qui me renvoie un StreamResponse quand je lui demande de télécharger une archive. J'arrive bien à récupérer l'objet JSON ou XHR qui revient avec ma requête AJAX de récupération de cette archive, mais je n'arrive pas à en récupérer le flux pour lancer le téléchargement.
    Est-ce que quelqu'un saurait m'aider sur le sujet et m'indiquer comment lancer ce téléchargement ?

    L'idée sous-jacente liée à l'utilisation d'AJAX est que lorsque je demande la récupération de l'archive, je lui passe un ensemble de paramètres qui déterminent comment est construite l'archive. Cette construction prend évidemment du temps et j'affiche en JS sur l'action AJAX un sablier et un message invitant à patienter. Quand je reçois mon retour AJAX, avec donc mon StreamResponse, j'aimerais lancer son téléchargement. Je n'ai évidement pas accès, avec cette API (privée) à l'adresse du fichier qui a été construit et qui va être téléchargé.

    Code JavaScript dans lequel je souhaiterais lancer le téléchargement du Stream --ligne en gras
    /**
    * Script prototype pour masquer et afficher la sélection des logs sur un appel AJAX de récupération des logs.
    */
    var ajaxLogsRetrieverDisplay = {
    onCreate : function() {
    Element.show('waitWhileRetrieving');
    Element.fade('logZone');
    },

    onComplete : function(xhr, json) {
    Element.show('logZone');
    Element.fade('waitWhileRetrieving');

    $('logsArchive').innerHTML = xhr.responseStream;
    }
    };

    /**
    * Enregistrement du script permettant "d'intercepter" les appels/retours AJAX.
    */
    AjaxLogsRetrieverTracker = {
    init : function() {
    Ajax.Responders.register(ajaxLogsRetrieverDisplay);
    }
    }
    Page TML d'où proviennent les appels JavaScript/AJAX
    <?xml version="1.0" encoding="utf-8" ?>
    <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
    <html xmlns="http://www.w3.org/1999/xhtml" xmlns:t="http://tapestry.apache.org/schema/tapestry_5_1_0.xsd" xmlns:p="tapestry:parameter">
    <head>
    <meta http-equiv="content-type" content="text/html; charset=utf-8" />
    </head>

    <t:content>
    <body t:type="layout" title="${message:page-titre}" menuCourant="41">

    <t:zone id="zoneLogSelection" t:id="zoneLogSelection">
    <div class="panel" t:type="zone" t:id="logZone" id="logZone"><t:form t:id="logsForm" t:zone="zoneLogSelection">
    <h1>${message:panel-log-title}</h1>
    <t:loop source="logSelectors" value="rootLog" formstate="ITERATION" encoder="encoder">
    <fieldset style="border-color: #e0e0e0;"><span id="${rootLog.indicator}"><legend><input t:type="checkbox" value="rootChecked"
    onclick="refreshChildrenCheckBox('${rootLog.indicator}')" />&nbsp;${rootLog.label}&nbsp; </legend></span> <t:loop source="rootLog.childLogSelector" value="nodeLog"
    formstate="ITERATION" encoder="encoder">
    <div class="champs"><label>${nodeLog.label}</label> <input t:type="checkbox" value="nodeChecked" style="width: auto"
    onclick="refreshParentCheckBox('${rootLog.indicator}')" /></div>
    </t:loop></fieldset>
    </t:loop>

    <div style="margin-left: auto; margin-right: auto; text-align: center;"><t:linkSubmit style="text-decoration: none" id="retrieveLogs"
    t:id="retrieveLogs">
    <img src="${asset:charte:images}/div/arrow.gif" border="0" />&nbsp;${message:telecharger-label}</t:linkSubmit>
    </div>
    </t:form></div>
    </t:zone>

    <t:zone id="zoneWaitWhileRetrieving" t:id="zoneWaitWhileRetrieving">
    <div id="waitWhileRetrieving" style="display: none">
    <h2>${message:recuperation-info}</h2><img id="imgStatusDomain" src="${asset:charte:images}/status/check.gif"
    alt="${message:recuperation-info}" title="${message:recuperation-info}" />
    <br />
    <i>${message:patience-info}</i></div>
    </t:zone>

    <div id="logsArchive">&nbsp;</div>
    </body>
    </t:content>
    </html>
    Code Java appelé --Il va de soit que le Thread.sleep n'est là que pour les tests....
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
    51
    52
    53
    54
    55
    56
    57
     
        /**
         * Méthode exécutée après le submit du formulaire.
         * 
         * @return le flux de l'archive des logs.
         */
        @Log
        StreamResponse onSuccess() {
            if (request.isXHR()) {
                LOGGER.info("Requete AJAX");
            } else {
                LOGGER.info("Requete non AJAX");
            }
     
            return new StreamResponse() {
                @Override
                public String getContentType() {
                    return TAR_GZ_CONTENT_TYPE;
                }
     
                @Override
                public InputStream getStream() throws IOException {
                    // final BeanDomaine beanDomaine = sessionManager.getDomaineProduit();
                    /***************************/
                    /** Paramètres du domaine **/
                    /***************************/
                    // final String envPrdt = beanDomaine.getEnvironnementProduit();
                    // final String rds = beanDomaine.getRds();
                    // final String dpt = beanDomaine.getDepartement();
                    // final String envData = beanDomaine.getEnvironnementDonnees();
                    try {
                        // return archiveRetriever.getLog(envPrdt, rds, dpt, envData, logSelectors);
     
                        final ByteArrayInputStream in =
                                new ByteArrayInputStream(new byte[] {'<', 'h', 't', 'm', 'l', '>', '<', 't', 'i', 't', 'l', 'e', '>', 't', 'o', 't', 'o', '<',
                                        '/', 't', 'i', 't', 'l', 'e', '>', '<', 'b', 'o', 'd', 'y', '>', 't', 'o', 't', 'o', '<', '/', 'b', 'o', 'd', 'y', '>',
                                        '<', '/', 'h', 't', 'm', 'l', '>'});
     
                        Thread.sleep(10000);
                        return in;
     
                        // } catch (final ArchiveRetrieverException e) {
                        // LOGGER.error("Erreur lors de l'obtention de l'archive de logs.", e);
                    } catch (final InterruptedException e) {
                        LOGGER.error("Impossible de dormir 10s...", e);
                    }
     
                    return null;
                }
     
                @Override
                public void prepareResponse(final Response response) {
                    LOGGER.info("Fichier renvoye : " + ConstantsUtils.VALUE_FOR_LOGGER, FILE_NAME);
                    response.setHeader("Content-Disposition", "attachment; filename=" + FILE_NAME);
                }
            };
        }
    Par avance, Merci pour votre aide,
    Si , et la ont échoué mais pas nous, pensez à dire et cliquez sur . Merci !

    Ici, c'est un forum, pas une foire. Il y a de respectables règles... à respecter !

  2. #2
    Inactif  

    Profil pro
    Inscrit en
    Mai 2010
    Messages
    345
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Mai 2010
    Messages : 345
    Points : 496
    Points
    496
    Par défaut
    Si tu veux TELECHARGER un contenu/fichier/stream, et donc ouvrir la boite de téléchargement du navigateur de l'utilisateur, ce n'est pas par ajax qu'il faut passer mais pas un window.location.href = "url de ton fichier en ajax".
    et coté serveur il faut changer le mime-type (content-type) pour être sur que l'utilisateur va télécharger le contenu. Dans la plupart des cas c'est :
    application/force-download, si ça ne passe pas, dans l'ancien temps (2003/2004, j'utilisais : application/octet-stream en ASP 2 )

    Mais sinon une recherche sur google avec les mots "forcer" et "telechargement" t'aurais permis de trouver une réponse à ton problème

  3. #3
    Membre éprouvé Avatar de leminipouce
    Homme Profil pro
    Ingénieur développement logiciels
    Inscrit en
    Janvier 2004
    Messages
    754
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 39
    Localisation : France, Haute Garonne (Midi Pyrénées)

    Informations professionnelles :
    Activité : Ingénieur développement logiciels
    Secteur : Agroalimentaire - Agriculture

    Informations forums :
    Inscription : Janvier 2004
    Messages : 754
    Points : 1 253
    Points
    1 253
    Par défaut
    Salut Duke.

    Citation Envoyé par dukej Voir le message
    Mais sinon une recherche sur google avec les mots "forcer" et "telechargement" t'aurais permis de trouver une réponse à ton problème
    Le problème n'est pas de télécharger le fichier, ni même de forcer le téléchargement. En l'occurence, je télécharge une archive tar.gz et mon content-type est "application/x-gzip". Pas de soucis si je renvoie en réponse de mon formulaire le ResponseStream, mon navigateur ouvre bien la fenêtre de téléchargement du fichier.

    Non, le vrai problème c'est de gérer ça en AJAX...
    Le workflow de mon application est le suivant :

    1. Choix parmis n listes des fichiers de logs à récupérer. (checkboxes)
    2. Demande de récupération de ces logs via un lien sur l'interface.
    3. Affichage à l'écran, sur l'action "onClick" du lien d'un message invitant à patienter pendant la création de l'archive
    4. Le serveur récupère tous les fichiers (qui se trouvent en l'occurence sur n serveurs physiques...) et crée une archive compressée de type tar.gz.
    5. Retour depuis le serveur de l'archive de logs --> Ouverture par le navigateur de la fenêtre de téléchargement.
    6. Affichage à l'utilisateur de l'écran de choix des fichiers à récupérer

    Si j'oublie l'étape 6, c'est très simple à faire. JJe fais une soumission de formulaire classique et tout se passe bien. Mais je ne mets jamais à jour mon écran une fois que l'archive de logs est prête à être téléchargée --> je n'ai qu'un seul retour depuis le serveur (logique quoi...) et comme c'est un Stream il n'y a pas de mise à jour de l'écran.
    Si je veux l'étape 6, je passe par AJAX, et je peux intercepter l'appel au serveur (fonction onCreate) et le retour du serveur (fonction onComplete).

    Dans ma fonction onComplete, je récupère bien le retour de mon serveur. Donc si je renvoie un 'Content-Type: text/html' je peux l'afficher par exemple dans un div de ma page, ou bien dans une popup. Aucun soucis là dessus.
    Par contre, si je renvoie justement un contenu à télécharger, je n'arrive pas à lancer le téléchargement. Il suffirait que je puisse ouvrir tout le retour du serveur (header inclus) dans un popup (que je ferme par exemple aussitôt après). Malheureusement je n'arrive pas à récupérer le header qui m'est renvoyé, ni forcer un header particuliers sur un popup (window.open).


    Aujourd'hui, j'ai une solution de contournement ou je renvoie un lien vers mon Stream à télécharger et j'affiche dynamiquement ce lien une fois la création de l'archive terminée. Mais j'aurais préféré automatiser un peu plus la chose et éviter que mon utilisateur est besoin de cliquer 2 fois (une pour créer l'archive, une seconde pour la télécharger).
    Si , et la ont échoué mais pas nous, pensez à dire et cliquez sur . Merci !

    Ici, c'est un forum, pas une foire. Il y a de respectables règles... à respecter !

  4. #4
    Inactif  

    Profil pro
    Inscrit en
    Mai 2010
    Messages
    345
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Mai 2010
    Messages : 345
    Points : 496
    Points
    496
    Par défaut
    quand ton stream te retourne ce lien, au lieu d'afficher ce lien, tu vérifies que c'est un "fichier à télécharger", et au lieu de faire :
    "J'affiche le contenu dans le innerHTML de mon joli div"
    tu fais un : window.location.href = monlien récupéré
    et là un téléchargement se lancera automatique.

    C'est ce que je te disais depuis le début, soit tu t'attends à recevoir un "fichier à télécharger", soit un contenu à afficher. Mais si ton application te retourne l'une des deux réponses, tu traites en fonction.

    Qu'est ce que tu ne comprends pas dans mon explication ?

  5. #5
    Membre éprouvé Avatar de leminipouce
    Homme Profil pro
    Ingénieur développement logiciels
    Inscrit en
    Janvier 2004
    Messages
    754
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 39
    Localisation : France, Haute Garonne (Midi Pyrénées)

    Informations professionnelles :
    Activité : Ingénieur développement logiciels
    Secteur : Agroalimentaire - Agriculture

    Informations forums :
    Inscription : Janvier 2004
    Messages : 754
    Points : 1 253
    Points
    1 253
    Par défaut
    Euh... à dire vrai c'est la partie redirection qui m'échappe.

    Aujourd'hui, quand j'ai mon retour AJAX, je me contente d'afficher un lien (au lieu de chercher à récupérer quelque chose dans mon innerHTML...).
    Ce lien c'est celui en gras ci-dessous. Et ce lien il me soumet le formulaire qui renvoie le StreamResponse :
    <t:zone id="zoneLogSelection" t:id="zoneLogSelection">
    <div class="panel" t:type="zone" t:id="logZone" id="logZone">
    <t:form t:id="logsForm" t:zone="zoneLogSelection">
    <h1>${message:panel-log-title}</h1>
    <t:loop source="logSelectors" value="rootLog" formstate="ITERATION" encoder="encoder">
    <fieldset style="border-color: #e0e0e0;" id="${rootLog.indicator}">
    <legend><input t:type="checkbox" value="rootChecked" onclick="refreshChildrenCheckBox('${rootLog.indicator}', this)" />&nbsp;${rootLog.label}&nbsp; </legend>
    <t:loop source="rootLog.childLogSelector" value="nodeLog" formstate="ITERATION" encoder="encoder">
    <div class="champs">
    <label>${nodeLog.label}</label><input t:type="checkbox" value="nodeChecked" style="width: auto" onclick="refreshParentCheckBox('${rootLog.indicator}')" />
    </div>
    </t:loop></fieldset>
    </t:loop>

    <div id="buildArchive" style="margin-left: auto; margin-right: auto; text-align: center;">
    <t:linkSubmit style="text-decoration: none" id="retrieveLogs" t:id="retrieveLogs" ><img src="${asset:charte:images}/div/arrow.gif" border="0" />&nbsp;${message:recuperer-label}</t:linkSubmit>
    <div id="downloadArchive" style="display: none">
    <a id="downloadLogs" t:type="actionlink" t:id="downloadLogs" href="#" onclick="Element.fade(this);">
    <img src="${asset:charte:images}/div/arrow.gif" border="0" />&nbsp;${message:telecharger-label}
    </a>

    </div>
    </div>
    </t:form>
    </div>
    </t:zone>
    Comme j'ai une soumission de formulaire, je vois pas bien comment m'en sortir avec ta solution à dire vrai...

    En tout cas, merci pour l'intérêt que tu me portes !
    Si , et la ont échoué mais pas nous, pensez à dire et cliquez sur . Merci !

    Ici, c'est un forum, pas une foire. Il y a de respectables règles... à respecter !

  6. #6
    Membre éprouvé Avatar de leminipouce
    Homme Profil pro
    Ingénieur développement logiciels
    Inscrit en
    Janvier 2004
    Messages
    754
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 39
    Localisation : France, Haute Garonne (Midi Pyrénées)

    Informations professionnelles :
    Activité : Ingénieur développement logiciels
    Secteur : Agroalimentaire - Agriculture

    Informations forums :
    Inscription : Janvier 2004
    Messages : 754
    Points : 1 253
    Points
    1 253
    Par défaut
    Je clos le sujet vu que mon contournement en affichant un lien pour le téléchargement fonctionne.
    Manque de temps, je peux pas consommer plus sur une solution plus automatisé, à mon grand regret.

    Concrètement, l'ouverture et la soumission de mon formulaire (ce que fait mon lien quand il est cliqué...) en JavaScript dans une pop-up est problématique vu que derrière j'ai Tapestry. J'arrive pas (manque de maîtrise sur le sujet) à générer un click sur ce lien... et que ça fonctionne.

    Merci encore en tout cas.
    Pouce
    Si , et la ont échoué mais pas nous, pensez à dire et cliquez sur . Merci !

    Ici, c'est un forum, pas une foire. Il y a de respectables règles... à respecter !

+ Répondre à la discussion
Cette discussion est résolue.

Discussions similaires

  1. Téléchargement de fichier
    Par casafa dans le forum Web & réseau
    Réponses: 21
    Dernier message: 19/06/2009, 00h34
  2. Réponses: 5
    Dernier message: 08/12/2005, 21h13
  3. Téléchargement de fichiers par HTTP / FTP
    Par Gladiator dans le forum Serveurs (Apache, IIS,...)
    Réponses: 2
    Dernier message: 07/12/2005, 12h28
  4. Réponses: 5
    Dernier message: 05/11/2005, 18h53
  5. [SOAP][XML][C#.NET] Téléchargement de fichiers XML
    Par juniorAl dans le forum XML/XSL et SOAP
    Réponses: 2
    Dernier message: 27/06/2005, 10h35

Partager

Partager
  • Envoyer la discussion sur Viadeo
  • Envoyer la discussion sur Twitter
  • Envoyer la discussion sur Google
  • Envoyer la discussion sur Facebook
  • Envoyer la discussion sur Digg
  • Envoyer la discussion sur Delicious
  • Envoyer la discussion sur MySpace
  • Envoyer la discussion sur Yahoo