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

Struts 1 Java Discussion :

[ Struts ] Envoyer un fichier au client


Sujet :

Struts 1 Java

  1. #1
    lr
    lr est déconnecté
    Membre régulier
    Profil pro
    Inscrit en
    Octobre 2003
    Messages
    338
    Détails du profil
    Informations personnelles :
    Localisation : Suisse

    Informations forums :
    Inscription : Octobre 2003
    Messages : 338
    Points : 114
    Points
    114
    Par défaut [ Struts ] Envoyer un fichier au client
    Salut,

    Je dois envoyer au client un fichier depuis une action struts. J'ai regardé la FAQ : http://java.developpez.com/faq/strut...files#download mais j'ai une IllegalStateException.

    Le fichier est bien envoyé au client (boîte de dialogue "enregistrer ou ouvrir") mais ensuite il y a l'erreur.

    Si j'enlève le os.close(), je n'ai plus d'erreur mais le fichier n'est plus envoyé.

    Avec os.flush() à la place de os.close(), c'est pareil.

    Comment faire pour que le fichier soit envoyé et que le déroulement s'enchaîne ensuite normalement sans erreur ?

    Merci d'avance
    Lilian

  2. #2
    Membre expérimenté
    Avatar de RanDomX
    Profil pro
    sans
    Inscrit en
    Mars 2003
    Messages
    579
    Détails du profil
    Informations personnelles :
    Localisation : France, Var (Provence Alpes Côte d'Azur)

    Informations professionnelles :
    Activité : sans

    Informations forums :
    Inscription : Mars 2003
    Messages : 579
    Points : 1 366
    Points
    1 366
    Par défaut
    tu as une trace ? un stacktrace ?

  3. #3
    lr
    lr est déconnecté
    Membre régulier
    Profil pro
    Inscrit en
    Octobre 2003
    Messages
    338
    Détails du profil
    Informations personnelles :
    Localisation : Suisse

    Informations forums :
    Inscription : Octobre 2003
    Messages : 338
    Points : 114
    Points
    114
    Par défaut
    Non, je suis désolé mais je développe dans jbuilder et l'erreur n'est pas plus explicite que ça

    Merci d'essayer de m'aider quand même...

  4. #4
    Membre éprouvé

    Profil pro
    Inscrit en
    Juin 2004
    Messages
    882
    Détails du profil
    Informations personnelles :
    Localisation : Suisse

    Informations forums :
    Inscription : Juin 2004
    Messages : 882
    Points : 948
    Points
    948
    Par défaut
    Citation Envoyé par lr
    Non, je suis désolé mais je développe dans jbuilder et l'erreur n'est pas plus explicite que ça

    Merci d'essayer de m'aider quand même...
    a la fin de ton action, fais un
    au lieu de
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    mapping.findForward("success");
    Le probleme c'est que la réponse est envoyée au client lorsque tu ecris dans l'outputStream (evidemment car c'est l'output de la réponse)

    Et lorsque tu fais un mapping.findForward tu tentes d'envoyer la réponse au client mais elle a déja etait envoyee => IllegalStateException
    cf. le principe est le meme pour les sendRedirect de l'objet response

  5. #5
    lr
    lr est déconnecté
    Membre régulier
    Profil pro
    Inscrit en
    Octobre 2003
    Messages
    338
    Détails du profil
    Informations personnelles :
    Localisation : Suisse

    Informations forums :
    Inscription : Octobre 2003
    Messages : 338
    Points : 114
    Points
    114
    Par défaut
    Merci pour ton aide,

    effectivement ça paraît logique. Alors maintenant je n'ai plus d'erreur et le fichier est bien envoyé au client. En revanche, je reste sur la même page. Comment passer à la jsp ou à l'action suivante ?

    J'ai essayé d'ajouter un response.sendRedirect mais on dirait que du coup l'envoi du fichier est ignoré.

    Est-ce que c'est parceque lorsque le browser reçoit un redirect dans l'entête, il l'effectue et ignore le reste ?

    Merci d'avance
    Lilian

  6. #6
    Membre éprouvé

    Profil pro
    Inscrit en
    Juin 2004
    Messages
    882
    Détails du profil
    Informations personnelles :
    Localisation : Suisse

    Informations forums :
    Inscription : Juin 2004
    Messages : 882
    Points : 948
    Points
    948
    Par défaut
    Citation Envoyé par lr
    Merci pour ton aide,

    effectivement ça paraît logique. Alors maintenant je n'ai plus d'erreur et le fichier est bien envoyé au client. En revanche, je reste sur la même page. Comment passer à la jsp ou à l'action suivante ?

    J'ai essayé d'ajouter un response.sendRedirect mais on dirait que du coup l'envoi du fichier est ignoré.

    Est-ce que c'est parceque lorsque le browser reçoit un redirect dans l'entête, il l'effectue et ignore le reste ?

    Merci d'avance
    Lilian
    Remets alors le forward comme il l'etait
    Juste avant le mapping.findForward essaie un

  7. #7
    lr
    lr est déconnecté
    Membre régulier
    Profil pro
    Inscrit en
    Octobre 2003
    Messages
    338
    Détails du profil
    Informations personnelles :
    Localisation : Suisse

    Informations forums :
    Inscription : Octobre 2003
    Messages : 338
    Points : 114
    Points
    114
    Par défaut
    Ca me donne à nouveau l'exception IllegalStateException avec cette fois-ci une belle stacktrace commençant par "getOutputStream a déjà été appelé pour cette réponse".

    Donc pour reprendre, j'ai maintenant l'envoi du fichier, puis la fermeture de l'outputstream puis reset de l'outputstream puis return mapping.findForward.

    Ci-dessous mon code, en cours de debug, merci d'être indulgent
    J'ajoute que je suis sous un framework et que c'est pour ça que ma classe n'étend pas directement l'action struts. Il se peut du coup que cette couche supplémentaire ajoute des problèmes mais, si vous le voulez bien, je souhaiterais que nous continuions en mettant ça de coté en considérant que le problème vient de mon code.

    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
    58
    59
    60
    61
    62
    63
    64
    65
    66
    67
    68
    69
    70
    71
    72
    73
    74
    75
    76
    77
    78
    79
    80
    81
    82
    83
    84
    85
    86
    87
    88
    89
    90
    91
    92
    93
    94
    95
    96
    97
    98
    99
    100
    101
    102
    103
    104
    105
    106
    107
    108
    109
    110
    111
    112
    113
    114
    115
    116
    117
    118
    119
    120
    121
    122
    123
    124
    125
    126
    127
    128
    129
    130
    131
    132
    133
    134
    135
    136
    137
    138
    139
    140
    141
    142
    143
     
    package tfi.fichier.ac;
     
    import org.apache.struts.action.ActionForward;
    import outilsStruts.config.CtiActionMapping;
    import outilsStruts.fb.GenFbBase;
    import javax.servlet.http.HttpServletRequest;
    import javax.servlet.http.HttpServletResponse;
    import outilsStruts.ac.*;
    import java.io.OutputStream;
    import java.io.FileInputStream;
    import java.io.BufferedInputStream;
    import java.io.InputStream;
     
    import java.sql.*;
    import oracle.sql.*;
    import oracle.jdbc.*;
    import java.io.File;
    import java.io.IOException;
    import java.io.PrintWriter;
     
     
    /**
     * <p>Title: </p>
     * <p>Description: </p>
     * <p>Copyright: Copyright (c) 2001</p>
     * <p>Company: CTI - EDM</p>
     * @author unascribed
     * @version 1.0
     */
     
    public class TfiAcTelechargerFichier extends GenAcBase
    {
     
       public TfiAcTelechargerFichier()
       {
       }
       public ActionForward execute(CtiActionMapping pMapping, GenFbBase pFormBean, HttpServletRequest parm3, HttpServletResponse pResponse) throws java.lang.Exception
       {
          /**@todo: implement this outilsStruts.ac.GenAcBase abstract method*/
          String result= null;
     
     
          String id = "1034";
     
          Connection con = null;
          PreparedStatement pstmt = null;
          ResultSet rs = null;
          BLOB blob = null;
     
          String selectforupdate = "SELECT FAO_X_BLOBDOC, FIC_C_NOM, FIC_C_CONTENTTYPE from FAO_T_FICHIER WHERE FIC_N_ID = ? ";
     
          try
          {
             DriverManager.registerDriver(new OracleDriver());
             con = DriverManager.getConnection("jdbc:oracle:thin:@xxxxxx:yyyy:zzz", "asdfasdf", "asdfasdf");
     
             pstmt = con.prepareStatement(selectforupdate);
             pstmt.setString(1,id);
     
             rs = pstmt.executeQuery();
     
             if(rs.next())
             {
                blob = ((OracleResultSet)rs).getBLOB(1);
                String fileName = rs.getString(2);
                String contentType = rs.getString(3);
     
                fileName = new File( fileName ).getName();
     
                if ( blob != null )
                {
                   if ( contentType != null )
                      pResponse.setContentType( contentType );
     
                   // Content-Disposition est utile pour présenter à l'utilisateur la fenêtre du browser permettant la sauvegarde du fichier
                   pResponse.setHeader("Content-Disposition", "attachment; filename=" + "\"" + fileName + "\"");
                   //pResponse.setHeader("Refresh", "5;");
     
     
                   InputStream is = blob.getBinaryStream();
                   OutputStream os = null;
                   //PrintWriter os = null;
                   try
                   {
                      os = pResponse.getOutputStream();
                      //os = pResponse.getWriter();
                   }
                   catch (IOException ioe0)
                   {
                      ioe0.printStackTrace();
                   }
     
                   BufferedInputStream data = new BufferedInputStream( is );
                   byte[] buf = new byte[100 * 1024];
                   //char[] charbuf = new char[100 * 1024];
                   int len;
     
                   while ((len = data.read(buf, 0, buf.length)) != -1)
                   {
                      //os.write(buf, 0, len);
                      os.write(buf, 0, buf.length);
                      len = data.read(buf, 0, buf.length);
                   }
                   is.close();
                   os.close();
                   data.close();
                }
                else
                {
     
                }
             }
             else
             {
                  int mar_1 =1;
             }
     
          }
          catch(SQLException esql)
          {
             esql.printStackTrace();
          }
          finally
          {
             try
             {
                rs.close();
                pstmt.close();
                con.close();
             }
             catch(SQLException esql)
             {
                esql.printStackTrace();
             }
          }
     
          pResponse.reset();
     
          result = "forward";
          return pMapping.findForward(result);
       }
    }

  8. #8
    Membre chevronné
    Homme Profil pro
    Dév. Java & C#
    Inscrit en
    Octobre 2002
    Messages
    1 414
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : Suisse

    Informations professionnelles :
    Activité : Dév. Java & C#
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Octobre 2002
    Messages : 1 414
    Points : 1 996
    Points
    1 996
    Par défaut
    Où est levée l'exception? Dans ton code?

    Malheureusement le message de l'exception est clair. Il faut enquêter
    qui a appelé getOutputStream ou getWriter avant toi.

    Ce qui me choque dans ton code
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    while ((len = data.read(buf, 0, buf.length)) != -1) 
                   { 
                      //os.write(buf, 0, len); 
                      os.write(buf, 0, buf.length); 
                      len = data.read(buf, 0, buf.length); 
                   }
    Désires-tu envoyer un buffer sur deux?

    EDIT: Il faut se rappeler qu'on ne peut envoyer qu'une seule réponse en HTTP

  9. #9
    lr
    lr est déconnecté
    Membre régulier
    Profil pro
    Inscrit en
    Octobre 2003
    Messages
    338
    Détails du profil
    Informations personnelles :
    Localisation : Suisse

    Informations forums :
    Inscription : Octobre 2003
    Messages : 338
    Points : 114
    Points
    114
    Par défaut
    Non, l'exception est levée après, après le return...

  10. #10
    Membre chevronné
    Homme Profil pro
    Dév. Java & C#
    Inscrit en
    Octobre 2002
    Messages
    1 414
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : Suisse

    Informations professionnelles :
    Activité : Dév. Java & C#
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Octobre 2002
    Messages : 1 414
    Points : 1 996
    Points
    1 996
    Par défaut
    Donc il faut voir du côté de votre framework...

    Bon courage et bonne semaine

  11. #11
    lr
    lr est déconnecté
    Membre régulier
    Profil pro
    Inscrit en
    Octobre 2003
    Messages
    338
    Détails du profil
    Informations personnelles :
    Localisation : Suisse

    Informations forums :
    Inscription : Octobre 2003
    Messages : 338
    Points : 114
    Points
    114
    Par défaut
    C'est possible, mais tu confirmes donc qu'à tes yeux le code ci-dessus devrait permettre l'envoi d'un fichier sans erreur ?

    Merci pour ton aide
    Lilian

  12. #12
    Membre expérimenté
    Avatar de viena
    Profil pro
    Inscrit en
    Juillet 2002
    Messages
    1 071
    Détails du profil
    Informations personnelles :
    Âge : 44
    Localisation : France, Nord (Nord Pas de Calais)

    Informations forums :
    Inscription : Juillet 2002
    Messages : 1 071
    Points : 1 512
    Points
    1 512
    Par défaut
    Je ne sais pas s'il existe un moyen propre de regler ce probleme. Mais en bidouillant, tu peux t'en sortir.
    Je ne pense pas que tu puisses faire un forward apres avoir lancer ton fichier en response. Donc, ce que tu peux faire, c'est gerer le cas dans ta JSP. C'est à dire que dans ton action, tu ajoutes un flag en request pour te permette de savoir que tu as fait ton traitement et que tu dois changer de page. Dans ta JSP, sur un onFocus de la page (windows), tu verifies que tu as ton flag (le mieux, c'est encore de le mettre dans un formulaire, c'est beaucoup plus simple à récupérer en JS... mais c'est encore moins propre... ). Si tu l'as, tu rappeles une autre action ou une autre page.

  13. #13
    Membre chevronné
    Homme Profil pro
    Dév. Java & C#
    Inscrit en
    Octobre 2002
    Messages
    1 414
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : Suisse

    Informations professionnelles :
    Activité : Dév. Java & C#
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Octobre 2002
    Messages : 1 414
    Points : 1 996
    Points
    1 996
    Par défaut
    Deux choses me chiffonnent dans ton code.

    1) Pourquoi lis-tu le blob en deux endroits et tu n'envoies que la première lecture?
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    while ((len = data.read(buf, 0, buf.length)) != -1)  /* Permière lecture */
                   { 
                      //os.write(buf, 0, len); 
                      os.write(buf, 0, buf.length);  /* On envoie 1ier lecture */
                      len = data.read(buf, 0, buf.length); /* 2ième lecture n'est jamais envoyée. Pourquoi? */
                   }
    2) Pourquoi utilises-tu la méthode reset? Cette méthode remet à zéro le buffer et les headers. Dans ton code, tu viens de perdre tout ce que tu désires envoyer.


    A part ces problèmes, ton code devrait fonctionner correctement.

  14. #14
    Membre éprouvé

    Profil pro
    Inscrit en
    Juin 2004
    Messages
    882
    Détails du profil
    Informations personnelles :
    Localisation : Suisse

    Informations forums :
    Inscription : Juin 2004
    Messages : 882
    Points : 948
    Points
    948
    Par défaut
    Citation Envoyé par jowo
    Deux choses me chiffonnent dans ton code.

    1) Pourquoi lis-tu le blob en deux endroits et tu n'envoies que la première lecture?
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    while ((len = data.read(buf, 0, buf.length)) != -1)  /* Permière lecture */
                   { 
                      //os.write(buf, 0, len); 
                      os.write(buf, 0, buf.length);  /* On envoie 1ier lecture */
                      len = data.read(buf, 0, buf.length); /* 2ième lecture n'est jamais envoyée. Pourquoi? */
                   }
    2) Pourquoi utilises-tu la méthode reset? Cette méthode remet à zéro le buffer et les headers. Dans ton code, tu viens de perdre tout ce que tu désires envoyer.


    A part ces problèmes, ton code devrait fonctionner correctement.
    En fait ses données sont envoyées par l'outputStream ( ce qui permet d'ouvrir une invite de téléchargement chez le client) de la réponse en suite lr souhaite simplement rediriger son client vers une autre page (de notification par exemple). La réponse aynt déjà été envoyée (via os) struts lancait une illegalStateException lors de la tentative de forward

  15. #15
    lr
    lr est déconnecté
    Membre régulier
    Profil pro
    Inscrit en
    Octobre 2003
    Messages
    338
    Détails du profil
    Informations personnelles :
    Localisation : Suisse

    Informations forums :
    Inscription : Octobre 2003
    Messages : 338
    Points : 114
    Points
    114
    Par défaut
    La réponse est envoyé au moment du
    C'est bien ça ?

    Merci pour votre aide
    Lilian

  16. #16
    Membre éprouvé

    Profil pro
    Inscrit en
    Juin 2004
    Messages
    882
    Détails du profil
    Informations personnelles :
    Localisation : Suisse

    Informations forums :
    Inscription : Juin 2004
    Messages : 882
    Points : 948
    Points
    948
    Par défaut
    Citation Envoyé par lr
    La réponse est envoyé au moment du
    C'est bien ça ?

    Merci pour votre aide
    Lilian
    Je pense plutôt qu'a ce moment là tu peux dire "ca y est la réponse a été envoyée au client, c'est terminé"

  17. #17
    lr
    lr est déconnecté
    Membre régulier
    Profil pro
    Inscrit en
    Octobre 2003
    Messages
    338
    Détails du profil
    Informations personnelles :
    Localisation : Suisse

    Informations forums :
    Inscription : Octobre 2003
    Messages : 338
    Points : 114
    Points
    114
    Par défaut
    Oui, c'est bien ce que je voulais dire Je crois avoir bien cerné le problème, il ne me reste plus qu'à trouver une "magouille" la plus propre possible pour faire ce que je veux.

    Il n'y a pas un moyen propre de le faire ? Je préfère éviter le javascript car rien ne me dit qu'il sera exécuté correctement.

    Je pense à une solution :

    1. L'utilisateur presse sur le bouton "download"
    2. L'action struts récupère le paramètre et forward à une jsp
    3. La jsp inclut un tag refresh qui appelle une autre action
    4. L'autre action (cf mon code) envoie le fichier

    Comme ça, le changement de page se fait avant l'envoi du fichier qui lui, ne provoque pas de changement de page...

  18. #18
    Membre éprouvé

    Profil pro
    Inscrit en
    Juin 2004
    Messages
    882
    Détails du profil
    Informations personnelles :
    Localisation : Suisse

    Informations forums :
    Inscription : Juin 2004
    Messages : 882
    Points : 948
    Points
    948
    Par défaut
    Citation Envoyé par lr
    Oui, c'est bien ce que je voulais dire Je crois avoir bien cerné le problème, il ne me reste plus qu'à trouver une "magouille" la plus propre possible pour faire ce que je veux.

    Il n'y a pas un moyen propre de le faire ? Je préfère éviter le javascript car rien ne me dit qu'il sera exécuté correctement.

    Je pense à une solution :

    1. L'utilisateur presse sur le bouton "download"
    2. L'action struts récupère le paramètre et forward à une jsp
    3. La jsp inclut un tag refresh qui appelle une autre action
    4. L'autre action (cf mon code) envoie le fichier

    Comme ça, le changement de page se fait avant l'envoi du fichier qui lui, ne provoque pas de changement de page...
    c'est quand même assez lourd je trouve mais à defaut d'avoir aucune autre solution

  19. #19
    Membre chevronné
    Homme Profil pro
    Dév. Java & C#
    Inscrit en
    Octobre 2002
    Messages
    1 414
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : Suisse

    Informations professionnelles :
    Activité : Dév. Java & C#
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Octobre 2002
    Messages : 1 414
    Points : 1 996
    Points
    1 996
    Par défaut
    Pour ma part, l'appel à os.close() me dérange.

    Car nous sommes pas responsable de l'ouverture de ce flux. Nous l'avons obtenu grâce à la méthode getOutputStream de l'objet response. C'est à ce dernier de s'en occuper.

    On peut utiliser la méthode flush() pour forcer l'envoi.

    Je demande l'avis d'autres personnes.

  20. #20
    Membre chevronné
    Homme Profil pro
    Dév. Java & C#
    Inscrit en
    Octobre 2002
    Messages
    1 414
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : Suisse

    Informations professionnelles :
    Activité : Dév. Java & C#
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Octobre 2002
    Messages : 1 414
    Points : 1 996
    Points
    1 996
    Par défaut
    Citation Envoyé par lr
    Oui, c'est bien ce que je voulais dire Je crois avoir bien cerné le problème, il ne me reste plus qu'à trouver une "magouille" la plus propre possible pour faire ce que je veux.

    Il n'y a pas un moyen propre de le faire ? Je préfère éviter le javascript car rien ne me dit qu'il sera exécuté correctement.

    Je pense à une solution :

    1. L'utilisateur presse sur le bouton "download"
    2. L'action struts récupère le paramètre et forward à une jsp
    3. La jsp inclut un tag refresh qui appelle une autre action
    4. L'autre action (cf mon code) envoie le fichier

    Comme ça, le changement de page se fait avant l'envoi du fichier qui lui, ne provoque pas de changement de page...
    C'est peut être lourd comme dit Benjamin, mais c'est une des meilleures solutions voire "LA SOLUTION".

Discussions similaires

  1. envoyer un fichier du client vers le serveur
    Par ysahel dans le forum Développement Web en Java
    Réponses: 4
    Dernier message: 27/05/2009, 22h07
  2. Réponses: 8
    Dernier message: 22/05/2007, 12h38
  3. Envoye de Fichier au client
    Par Cronycs dans le forum Struts 1
    Réponses: 14
    Dernier message: 27/04/2007, 14h58
  4. Réponses: 2
    Dernier message: 22/06/2006, 12h09
  5. Serveur/Client UDP: comment envoyer un fichier avec mon code
    Par danje dans le forum Entrée/Sortie
    Réponses: 7
    Dernier message: 21/12/2005, 14h54

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