Récupération des fichiers de base de données

Résolu/Fermé
newzinoucha20 Messages postés 33 Date d'inscription samedi 4 mars 2017 Statut Membre Dernière intervention 30 mars 2019 - 7 févr. 2018 à 02:02
KX Messages postés 16733 Date d'inscription samedi 31 mai 2008 Statut Modérateur Dernière intervention 31 janvier 2024 - 8 févr. 2018 à 08:40
Bonjour tout le monde,

je suis en cours de dévellopper une application e_learning bureau en javafx, mon probleme c'est que j'ai enregistré un fichier pdf dans ma base de données (mysql) sous le type blob et a partir de mon programme je dois le récupérer j'ai trouvé un petit programme et j'arrive à le récupere mais le fichier est vide . je sera trés reconnaissante si vous me corriger mon erreur .
J'ai entendu parlé qu'il y a une autre méthode d'entregistrer les fichiers sous une base de données en indiquant juste le chemin du fichier mais je ne métrise pas cette méthode.
merci d'avance .

1 réponse

KX Messages postés 16733 Date d'inscription samedi 31 mai 2008 Statut Modérateur Dernière intervention 31 janvier 2024 3 015
7 févr. 2018 à 10:37
Bonjour,

Merci de coller ton code avec les balises de code associées plutôt que de mettre une image. Je ne vais pas m'amuser à retaper le code qui est sur ton image, un copier-coller serait tellement plus simple.

"J'ai entendu parlé qu'il y a une autre méthode d'entregistrer les fichiers sous une base de données en indiquant juste le chemin du fichier mais je ne métrise pas cette méthode."
C'est en effet le plus simple et le plus pertinent. Une base de données c'est fait pour requêter des données, mais un BLOB n'est pas requêtable (tu ne vas pas faire where sur le contenu du fichier), donc stocker un fichier en base de données est inutile, en plus si un fichier est utilisé plusieurs fois, tu devrais le dupliquer dans ta base alors que tu pourrais juste faire un lien vers ce fichier.
Ce qu'il faut c'est avoir un système de fichiers à côté, par exemple D:\ où tu vas stocker tous tes fichiers.
Il ne reste alors plus qu'à mettre dans ta base de données, l'emplacement du fichier, exemple path\file.
En requêtant ta base tu récupère path\file, tu sais que le système de fichier c'est D:\ donc tu vas récupérer le fichier dans D:\path\file.
1
newzinoucha20 Messages postés 33 Date d'inscription samedi 4 mars 2017 Statut Membre Dernière intervention 30 mars 2019
Modifié le 7 févr. 2018 à 19:35
merci bcp tout d'abord pour votre réponse , et je m' excuse pour le screen .voilà le code:
package controller;

import java.io.File;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;

import javafx.application.Application;
import javafx.stage.Stage;

public class essai extends Application  {
 public void start(Stage primaryStage) throws FileNotFoundException {
  
///**********Attribut pour relier projet a BD
    Connection cnn=null;
    PreparedStatement prepared=null;    
    ResultSet res=null;
   //connexion avec base de données****
    cnn=(Connection) ConnectBd.connexionBD();
    File f=new File("resume1.pdf");
    FileOutputStream output=new FileOutputStream(f);
    String sql="select * from cours";
      try {
  prepared=cnn.prepareStatement(sql);
  res=prepared.executeQuery();
  while(res.next()){
   InputStream input=res.getBinaryStream("file");
   byte[] buff=new byte[1024];
   while(input.read(buff)>0){
    output.write(buff);
   }
    
   System.out.println("c fait");
   
  }
 } catch (SQLException | IOException e) {
  // TODO Auto-generated catch block
  e.printStackTrace();
 }
       }

 public static void main(String[] args) {
  launch(args);
 }}

le code s'éxecute mais le fichier montre cette erreur: le fichier est endommagé ou ne peut pas etre récupérer

Pour la deuxième idée de mettre juste le path du fichier est-ce que le champ ou je vais mettre ce path sera de type varchar?? et comment je vais mentionner dans le programme que c'est un path de mon fichier ?
mercii d'avance
0
KX Messages postés 16733 Date d'inscription samedi 31 mai 2008 Statut Modérateur Dernière intervention 31 janvier 2024 3 015 > newzinoucha20 Messages postés 33 Date d'inscription samedi 4 mars 2017 Statut Membre Dernière intervention 30 mars 2019
7 févr. 2018 à 20:13
"le fichier est endommagé"
En effet, il y a plusieurs erreurs dans ton code qui font qu'il doit te manquer des données.

1) Tu ne fermes jamais tes flux, ça c'est catastrophique avec la base de données, parce que ça veut dire qu'elle garde ouvre une nouvelle connexion à chaque fois mais sans jamais la fermer, à un moment la base de donnée refusera d'ouvrir de nouvelles connexion.
Quant aux fichiers, si tu ne le fermes pas explicitement, les derniers caractères peuvent ne pas avoir été flushés : le système va attendre d'avoir assez de données avant d'aller écrire sur le disque, mais s'il n'y a pas de fermeture propre de fichier, certaines données en attente peuvent ne jamais être écrite.
Il faut soit que tu fermes tout explicitement avec la méthode close(), soit que tu utilises un try-with-resources (recommandé) et ce pour chacun des éléments ouverts : Connection, PreparedStatement, ResultSet, FileOutputStream et FileInputStream.

2)
while(input.read(buff) > 0) { output.write(buff); }

Là il faut lire la documentation pour savoir ce que renvoie la méthode read. Mais il est possible que cela renvoie 0 même si le flux n'est pas terminé, c'est juste que c'est lent (ce qui arrive par exemple quand tu télécharges un fichier, ça mets du temps à venir), dans la documentation il est précisé que c'est -1 qui est renvoyé quand le flux est terminé.
De plus, la méthode write va écrire l'intégralité du tableau, soit 1024 octets, alors que tu en as peut-être lu moins, il ne faut écrire que le nombre exact d'octets que tu en as lu, avec un code du genre
while((n = input.read(buff)) != -1) { output.write(buff, n); }

Remarque : ce genre de méthode de transfert de flux existent déjà en Java, il n'est pas nécessaire de les réécrire toi même en prenant le risque à chaque fois de faire une erreur.

3) Tu as mal géré tes boucles, ton ResultSet va te renvoyer plusieurs fichiers (un par ligne dans ta table) mais tu vas tout écrire dans le même fichier de résultat ce qui est évidemment faux.
Tu dois créer autant de fichier de résultat que de lignes dans ta table de base de données.

Exemple :

import java.io.*;
import java.nio.file.*;
import java.sql.*;

try (Connection connection = ConnectBd.connexionBD();
        Statement statement = connection.createStatement();
        ResultSet resultSet = statement.executeQuery("select * from cours")) {
    for (int i = 1; resultSet.next(); i++) {
        try (InputStream inputStream = resultSet.getBinaryStream("file")) {
            Path path = Paths.get("resume" + i + ".pdf");
            Files.copy(inputStream, path, StandardCopyOption.REPLACE_EXISTING);
        } catch (IOException e) {
            e.printStackTrace();
        }
    }
} catch (SQLException e) {
    e.printStackTrace();
}

4) "est-ce que le champ ou je vais mettre ce path sera de type varchar?? et comment je vais mentionner dans le programme que c'est un path de mon fichier ?"
Oui, c'est un varchar, donc tu le récupères sous forme de String et ce sera l'emplacement de ton fichier que tu pourras ensuite ouvrir avec un InputStream ou copier directement avec la méthode de la classe Files.

String file = resultSet.getString("file");
Path input = Paths.get(file), output = Paths.get("resume" + i + ".pdf");
Files.copy(input, output, StandardCopyOption.REPLACE_EXISTING);
0
newzinoucha20 Messages postés 33 Date d'inscription samedi 4 mars 2017 Statut Membre Dernière intervention 30 mars 2019
8 févr. 2018 à 03:06
je vous remercie infiniment la première méthode n'a pas marché mais la deuxième fonctionne très bien merciiii.
0
KX Messages postés 16733 Date d'inscription samedi 31 mai 2008 Statut Modérateur Dernière intervention 31 janvier 2024 3 015 > newzinoucha20 Messages postés 33 Date d'inscription samedi 4 mars 2017 Statut Membre Dernière intervention 30 mars 2019
8 févr. 2018 à 08:40
Remarque : la première méthode n'a peut-être pas marché parce que les données étaient déjà corrompus en base au moment où tu les as importé, il aurait fallu corriger le code de l'import aussi.
0