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

Langage Java Discussion :

Problème de corruption de données lors du téléchargement de fichiers PDF ou DOC.


Sujet :

Langage Java

Vue hybride

Message précédent Message précédent   Message suivant Message suivant
  1. #1
    Membre habitué
    Profil pro
    Inscrit en
    Août 2007
    Messages
    8
    Détails du profil
    Informations personnelles :
    Âge : 40
    Localisation : France, Bouches du Rhône (Provence Alpes Côte d'Azur)

    Informations forums :
    Inscription : Août 2007
    Messages : 8
    Par défaut Problème de corruption de données lors du téléchargement de fichiers PDF ou DOC.
    Bonjour à tous.
    Dans le programme que je suis entrain de corriger, je dois, à un moment donné, télécharger un fichier sur internet et l'enregistrer sur le disque de la machine.
    (Env : Windows 7, Java7).
    Ce sont des fichiers doc et pdf.
    Le problème 'est que j'ai des erreurs qui apparaissent dans le "code" du fichier récupéré qui le rendent illisible. Le poids du fichier est proche de la taille réelle. (à quelques octets pres). Et quand je l'ouvre avec un lecteur de pdf, par exemple, ça m'affiche une page blanche.

    Voici le morceau de 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
     
                                                    try
    						{
     
    							System.out.println(cvDL);
    							InputStream in = new 														ByteArrayInputStream(cvDL.getBytes());
    							FileOutputStream writenFile = new FileOutputStream(
    									fichier);
     
    							byte[] buffer = new byte[1024];
    							int read;
     
    							while ((read = in.read(buffer)) > 0)
    							      writenFile.write(buffer, 0, read);
     
    							writenFile.flush();
    							writenFile.close();
    						}
    						catch (Exception e)
    						{
    							e.printStackTrace();
    						}
    cvDL est du type String et contient le fichier récupéré par une requête HTTP ici :

    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
     
    				HttpPost httppost = new HttpPost(cv.getPathDownloadFile());
    				HttpResponse response = execute(httpclient, httppost, nameValuePairs);
     
    				String cvDL = "";
    				try
    				{
    				BufferedReader reader = new BufferedReader(new InputStreamReader(response
    						.getEntity().getContent()));
    				String ligne = "";
    				while ((ligne = reader.readLine()) != null)
    				{
    					cvDL += ligne + "\n";
    				}
    				reader.close();
    				}
    				catch (IllegalStateException e)
    				{
    				e.printStackTrace();
    				}
    				catch (IOException e)
    				{
    				e.printStackTrace();
    				}


    Je n'arrive pas à trouver d'où ces erreurs de copie peuvent venir.
    Problème de buffer ? d'encodage ?

  2. #2
    Modérateur

    Profil pro
    Inscrit en
    Septembre 2004
    Messages
    12 582
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Septembre 2004
    Messages : 12 582
    Par défaut
    Il ne faut pas utiliser de Reader ni de String pour copier des fichiers. Uniquement des InputStream et des OutputStream. C'est la différence entre texte et binaire.

    Tu dois modifier cet extrait de code pour qu'il n'y ait aucun Reader nulle part. Normalement, il n'y aura plus de String.getBytes() non plus.
    N'oubliez pas de consulter les FAQ Java et les cours et tutoriels Java

  3. #3
    Membre habitué
    Profil pro
    Inscrit en
    Août 2007
    Messages
    8
    Détails du profil
    Informations personnelles :
    Âge : 40
    Localisation : France, Bouches du Rhône (Provence Alpes Côte d'Azur)

    Informations forums :
    Inscription : Août 2007
    Messages : 8
    Par défaut
    Merci pour la réponse c'était bien ça.

    Voici le code corrigé :

    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
    			httppost = new HttpPost(pathDownloadFile);
    			response = execute(httpclient, httppost, nameValuePairs);
     
    			DataInputStream cvDL = null;
    			try
    			{
    				cvDL = new DataInputStream(response
    						.getEntity().getContent());
    			}
    			catch (IllegalStateException e)
    			{
    			e.printStackTrace();
    			}
    			catch (IOException e)
    			{
    			e.printStackTrace();
    			}
    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
     
    						try
    						{
     
    							FileOutputStream writenFile = new FileOutputStream(fichier);
     
    							byte[] buffer = new byte[1024];
    							int read;
     
    							while ((read = cvDL.read(buffer)) > 0)
    							     writenFile.write(buffer, 0, read);
     
    							writenFile.flush();
    							writenFile.close();
    						}
    						catch (Exception e)
    						{
    							e.printStackTrace();
    						}
    Je ne sais pas si c'est ce qu'il y a de mieux, mais ça marche bien.

  4. #4
    Modérateur

    Profil pro
    Inscrit en
    Septembre 2004
    Messages
    12 582
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Septembre 2004
    Messages : 12 582
    Par défaut
    Ça va plutôt bien. Quelques remarques :

    - Le close() doit être dans le finally, pas dans le try !!

    En fait, depuis Java 7, le mieux est d'utiliser un try-with-resources, genre :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    try(OutputStream writtenFile = new FileOutputStream(fichier)) {
      byte[] buffer = new byte[1024];
      int read;
     
      while ((read = cvDL.read(buffer)) > 0) {
        writtenFile.write(buffer, 0, read);
      }
    }
    writtenFile étant déclaré comme une ressource du try, il sera fermé automatiquement à la sortie du try, en cas d'échec comme de réussite.

    - Il ne faut pas oublier de fermer le flux en lecture. Lui aussi avec un try-with-resource, de préférence.

    - Pourquoi faire un catch sur l'Exception ? Si ça n'a pas marché ça n'a pas marché, il vaut mieux remonter l'erreur à l'appelant.

    - flush() ne sert à rien avant un close(). Et de manière générale, il n'est utile que quand on sait exactement pourquoi on le fait.

    - DataInputStream n'était pas utile. Il suffisait de garder le InputStream donné par getContent()
    N'oubliez pas de consulter les FAQ Java et les cours et tutoriels Java

  5. #5
    Expert éminent
    Avatar de adiGuba
    Homme Profil pro
    Développeur Java/Web
    Inscrit en
    Avril 2002
    Messages
    13 938
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France

    Informations professionnelles :
    Activité : Développeur Java/Web
    Secteur : Transports

    Informations forums :
    Inscription : Avril 2002
    Messages : 13 938
    Billets dans le blog
    1
    Par défaut
    Salut,

    Citation Envoyé par thelvin Voir le message
    - flush() ne sert à rien avant un close(). Et de manière générale, il n'est utile que quand on sait exactement pourquoi on le fait.
    +1 pour tous le reste, mais perso j'aurais tendance à laisser le flush() à la fin du traitement.


    Et justement sans connaitre l'implémentation concrête du stream, ca ne coûte rien de le forcer et çà évite de mauvaise surprise...


    a++

  6. #6
    Modérateur

    Profil pro
    Inscrit en
    Septembre 2004
    Messages
    12 582
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Septembre 2004
    Messages : 12 582
    Par défaut
    Ma foi, je n'ai jamais eu de problème. Et la JavaDoc de close() est parfaitement claire : s'il y a du traitement à finir avant de fermer, close() doit s'en occuper.

    Cas typique d'un flux base64, ou zippé, ou chiffré, où il y a des données pending à la fin que flush() ne peut pas envoyer, parce que le traitement n'est pas le même si ces données sont les dernières ou s'il y en aura d'autres après.

    Un résultat différent entre flush() puis close(), ou juste close(), démontre un bug dans l'implémentation du stream. Bon les bugs, ça existe, certes.
    N'oubliez pas de consulter les FAQ Java et les cours et tutoriels Java

  7. #7
    Membre habitué
    Profil pro
    Inscrit en
    Août 2007
    Messages
    8
    Détails du profil
    Informations personnelles :
    Âge : 40
    Localisation : France, Bouches du Rhône (Provence Alpes Côte d'Azur)

    Informations forums :
    Inscription : Août 2007
    Messages : 8
    Par défaut
    Merci beaucoup pour les précisions que je viens d'intégrer.

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

Discussions similaires

  1. Problème de récupération des données lors d'un export
    Par lolilola dans le forum Servlets/JSP
    Réponses: 1
    Dernier message: 22/12/2009, 17h24
  2. [WD14] Problème de corruption de données HF C/S
    Par KCrevette dans le forum WinDev
    Réponses: 2
    Dernier message: 08/12/2009, 09h33
  3. Réponses: 2
    Dernier message: 12/09/2008, 09h29
  4. Problème de cohérence de données lors de suppression d'une ligne
    Par Alphadjo dans le forum Macros et VBA Excel
    Réponses: 7
    Dernier message: 30/06/2008, 20h07
  5. Problème de base de données lors de mon stage
    Par mmanta1 dans le forum Sécurité
    Réponses: 3
    Dernier message: 09/06/2007, 21h15

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