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

Python Discussion :

mysql et fichiers joints


Sujet :

Python

Vue hybride

Message précédent Message précédent   Message suivant Message suivant
  1. #1
    Membre confirmé
    Homme Profil pro
    Ingénieur développement de composants
    Inscrit en
    Décembre 2019
    Messages
    113
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 36
    Localisation : France, Haute Savoie (Rhône Alpes)

    Informations professionnelles :
    Activité : Ingénieur développement de composants

    Informations forums :
    Inscription : Décembre 2019
    Messages : 113
    Par défaut mysql et fichiers joints
    Bonjour,
    je cherche à inclure dans une base de données mysql des fichiers joints (pdf, image et autre extensions type pack office...).
    après quelques recherches, il semble que cela doit se dérouler via l’utilisation de la typologie BLOB de la colonne servant à accueillir le/les fichiers.
    aussi, il semble que les fichiers doivent être binarisés pour être stockés dans la table.

    pour la binarisation j'utilise les deux ligne suivantes (pj = chemin du fichier à joindre):
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    with open(pj, 'rb') as file:
        binaryData = file.read()
    par la suite j'insère le fichier via la ligne suivante (exemple):

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    data = ("AAAA","BBBB", binaryData)
    sql_add_query = """INSERT INTO table (Col1, Col2, Attached_file) VALUES (%s,%s,%s)"""
    cursor.execute(sql_add_query, data)
    jusque là, pas de plantage... ça tourne...

    maintenant pour revenir lire le fichier attaché dans la BDD, j'utilise les lignes suivantes:

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    sql_fetch_blob_query = """SELECT * FROM table where colonne_visee = 'test'"""
    cursor.execute(sql_fetch_blob_query)
    record = cursor.fetchall()
     
    for row in record:
        print(row[2])
        with open(r"chemin", 'wb') as file:
            file.write(row[2])
    ici aussi, ça tourne... sauf que le fichier généré est impossible à ouvrir...

    à priori, j'ai l'impression que ce qui ne va pas c'est une histoire de format.
    je fait un binaire (b'\xff...') qui se transforme en str ("b'\xff...'").
    sauf que je n'arrive ni à intégrer dans la base de données directement un format bytes ni à re-convertir correctement le str en bytes... pour le lire

    qu'est qui ne va pas? est-ce la bonne méthode pour attacher des fichiers à une colonne? au fait possible de mettre plusieurs fichiers dans une "cellule" d'une colonne?

    NB: je débute à peine en mysql! je suis preneur de tout conseils :-)

    merci,
    cordialement,

  2. #2
    Expert confirmé Avatar de papajoker
    Homme Profil pro
    Développeur Web
    Inscrit en
    Septembre 2013
    Messages
    2 323
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Nièvre (Bourgogne)

    Informations professionnelles :
    Activité : Développeur Web
    Secteur : High Tech - Multimédia et Internet

    Informations forums :
    Inscription : Septembre 2013
    Messages : 2 323
    Par défaut
    bonjour

    En fait il est plus que rare que l'on sauvegarde des binaires dans une base de donnée. Pas d'intérêt car pas de recherche sur ces fichiers et surtout il devient impossible de faire une sauvegarde de la base de donnée au format sql
    On préfère avoir un répertoire (avec droits en écriture si serveur) ou l'on va sauvegarder ces fichiers. Puis dans la table, on ne passe que le nom du fichier

  3. #3
    Membre prolifique
    Avatar de Sve@r
    Homme Profil pro
    Ingénieur développement logiciels
    Inscrit en
    Février 2006
    Messages
    12 830
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Oise (Picardie)

    Informations professionnelles :
    Activité : Ingénieur développement logiciels
    Secteur : Aéronautique - Marine - Espace - Armement

    Informations forums :
    Inscription : Février 2006
    Messages : 12 830
    Billets dans le blog
    1
    Par défaut
    Bonjour
    Citation Envoyé par clement_74 Voir le message
    ici aussi, ça tourne... sauf que le fichier généré est impossible à ouvrir...
    à priori, j'ai l'impression que ce qui ne va pas c'est une histoire de format.
    je fait un binaire (b'\xff...') qui se transforme en str ("b'\xff...'").
    A priori ta méthode d'écriture me semble bonne (ouvrir en "wb" et écrire directement ce que tu as lu). Il faudrait que tu fasses un test avec un fichierX. Tu le sauvegardes, le récupère ensuite en fichierY et là tu lances un md5 voir s'ils sont identiques. A priori ils ne le seront pas (sinon le fichier Y pourrait être ouvert) mais tu en auras la preuve.

    Ensuite, il te faut tester sans Python (voir d'où provient le merdier). Avec des ordres mysql tu tentes la sauvegarde et la restauration, c'est la base. Parce que quand tu sauras le faire manuellement, tu pourras alors claquer la méthode dans Python. Ca fait longtemps que j'ai pas touchéà MySQL mais il me semble, dans mes souvenirs, que la gestion des blobs se faisait de façon différente des insert/select normaux.

    J'ai trouvé cette page qui décrit la procédure manuellement.

    Citation Envoyé par papajoker Voir le message
    En fait il est plus que rare que l'on sauvegarde des binaires dans une base de donnée.
    J'ai eu le cas une fois. Une bdd dans laquelle il fallait pouvoir enregistrer des pièces-jointes au format images et/ou pdf. J'ai proposé ton idée (la PJ dans un dossier et la bdd contenant le nom) mais on m'a refusé, le cahier des charges voulait tout dans la bdd (facilité de déplacement, tu dumpes la bdd tu as tout).
    Un souci majeur était qu'une même image (ou pdf) pouvait être intégré plusieurs fois à différents niveaux mais il ne fallait pas en retour stocker n fois la même image. Je l'ai résolu via le md5 (la table "pj" contenait le md5 du fichier en clef primaire, le nb de fois où elle était insérée et le document au format binaire). Et j'avais même mis un trigger pour intercepter tout insert et/ou delete pour que le client ne soit pas embêté (chaque insert/delete checkait le nb de fois, et faisait selon le cas un simple incrément/décrément).

    Citation Envoyé par papajoker Voir le message
    Pas d'intérêt car pas de recherche sur ces fichiers
    Là je ne suis pas certain de comprendre. A quel type de recherche tu penses ? Sur le contenu ? Dans mon cas ce n'était pas demandé mais si vraiment SQL ne propose pas de méthode de recherche dans la data binaire, au pire, rien n'interdit, lors de la recherche, de descendre le binaire en fichier disque, rechercher dans le fichier et l'effacer à l'issue. Long mais toujours possible.

    Citation Envoyé par papajoker Voir le message
    et surtout il devient impossible de faire une sauvegarde de la base de donnée au format sql
    Ah non, là je ne suis pas d'accord. Pour MySQL je sais pas mais ma bdd était sout Postgres et l'outil de dump associé permet parfaitement la sauvegarde de ce type de data. Je l'ai fait, testé, la bdd récupérée est identique en tout point à la bdd initiale. Ok le dump est gargantuesque (plus de 1Go ce qui est assez gros pour un fichier SQL sur lequel il devient difficile d'intervenir manuellement si besoin) mais parfaitement viable et récupérable via psql.
    Mon Tutoriel sur la programmation «Python»
    Mon Tutoriel sur la programmation «Shell»
    Sinon il y en a pleins d'autres. N'oubliez pas non plus les différentes faq disponibles sur ce site
    Et on poste ses codes entre balises [code] et [/code]

  4. #4
    Expert éminent
    Homme Profil pro
    Architecte technique retraité
    Inscrit en
    Juin 2008
    Messages
    21 738
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Manche (Basse Normandie)

    Informations professionnelles :
    Activité : Architecte technique retraité
    Secteur : Industrie

    Informations forums :
    Inscription : Juin 2008
    Messages : 21 738
    Par défaut
    Salut,

    Citation Envoyé par clement_74 Voir le message
    qu'est qui ne va pas? est-ce la bonne méthode pour attacher des fichiers à une colonne? au fait possible de mettre plusieurs fichiers dans une "cellule" d'une colonne?
    Une colonne de type BLOB va récupérer le contenu du fichier sous forme binaire. Et si on veut en faire une sorte de fichier, il faut utiliser io.(String|Bytes)IO: on ne peut pas faire "open" sur une chaîne de caractères/séquence de bytes.

    Ceci dit, si on a déjà une séquence de bytes, plus la peine de lire le fichier.

    Le contenu d'un fichier est une séquence de bytes. On sait ajouter des séquences de bytes. Donc on peut stocker le contenu de plusieurs fichiers dans un BLOB (mais on ne saura pas où commencent/finissent les différents fichiers après).

    - W
    Architectures post-modernes.
    Python sur DVP c'est aussi des FAQs, des cours et tutoriels

  5. #5
    Membre Expert
    Homme Profil pro
    Développeur informatique
    Inscrit en
    Février 2003
    Messages
    1 603
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France

    Informations professionnelles :
    Activité : Développeur informatique
    Secteur : Industrie

    Informations forums :
    Inscription : Février 2003
    Messages : 1 603
    Par défaut
    Citation Envoyé par clement_74 Voir le message
    au fait possible de mettre plusieurs fichiers dans une "cellule" d'une colonne?
    Dans ce cas là, pourquoi ne pas envisager de stocker dans un champ un fichier compressé ?

  6. #6
    Membre prolifique
    Avatar de Sve@r
    Homme Profil pro
    Ingénieur développement logiciels
    Inscrit en
    Février 2006
    Messages
    12 830
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Oise (Picardie)

    Informations professionnelles :
    Activité : Ingénieur développement logiciels
    Secteur : Aéronautique - Marine - Espace - Armement

    Informations forums :
    Inscription : Février 2006
    Messages : 12 830
    Billets dans le blog
    1
    Par défaut
    Citation Envoyé par Arioch Voir le message
    Dans ce cas là, pourquoi ne pas envisager de stocker dans un champ un fichier compressé ?
    Au niveau programmation ça ne change rien. Que tu mettes plusieurs fichiers binaires "nature" ou compressés, ça reste au final du binaire, il faut quand-même trouver le moyen (si tu veux en mettre plusieurs dans le champ) de les distinguer.
    Après il faut voir ce que ça apporte. La compression à l'insert et la décompression au select prend du temps (plus pour la compression que pour la décompression). Et si le fichier se prête mal à la compression, le gain de taille risque de ne pas être à la hauteur de la complexité apportée au code.
    Pour mon cas perso exposé précedemment, je n'avais pas jugé utile de l'implémenter
    Mon Tutoriel sur la programmation «Python»
    Mon Tutoriel sur la programmation «Shell»
    Sinon il y en a pleins d'autres. N'oubliez pas non plus les différentes faq disponibles sur ce site
    Et on poste ses codes entre balises [code] et [/code]

  7. #7
    Membre confirmé
    Homme Profil pro
    Ingénieur développement de composants
    Inscrit en
    Décembre 2019
    Messages
    113
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 36
    Localisation : France, Haute Savoie (Rhône Alpes)

    Informations professionnelles :
    Activité : Ingénieur développement de composants

    Informations forums :
    Inscription : Décembre 2019
    Messages : 113
    Par défaut
    Bonsoir,
    merci pour vos réponses, j'essaie du coup différentes choses... (avec plus ou moins de succès...)
    ci dessous le code tel qu'il est actuellement.
    je pense que ça "simule" bien mon problème de binarisation puis de ré-écriture.
    ça tourne, les fichiers sont bien lisibles et identiques aux originaux (même sans passer par mysql) et en considérant plusieurs fichiers (issus d'une liste).

    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
     
    liste_pj = ["photo2.jpg", "photo3.png", "test.pdf"]
    liste_pj2 = []
    liste_pj_bin = []
    new_str_concat = ""
    i = 0
     
    for noms in enumerate(liste_pj):
        liste_pj2.append("new_" + str(noms[1]))
     
    for pj in liste_pj:   
        with open(pj, 'rb') as file:
            binaryData = file.read()
            liste_pj_bin.append(binaryData)
     
     
    liste_from_mysql=str(liste_pj_bin)
    #mauvaise idée... reconvertir un tel str apparait impossible..??
    #l'idée aurait été de remplacer le "liste_pj_bin" de la liste ci-dessous (qui est une vraies liste d'objets binarisés) par "liste_from_mysql" (qui n'est finalement qu'un gros string) 
     
    for pj_bin in liste_pj_bin:
        with open(liste_pj2[i], 'wb') as file:
            file.write(liste_pj_bin[i])
        i = i + 1
    du coup pour être vraiment comparable au fait d'envoyer/récupérer de la data depuis la bdd sql, il reste "juste" à convertir/splitter le str de liste avant la dernière boucle...
    j'ai essayé de m'en sortir avec: str_binaire.decode('ascii') puis string.encode('ascii')... sans succès...
    c'est pour cette étape que le md5 est utile? pour convertir une chaine "binaire" en chaine de caractère?

    merci

  8. #8
    Membre prolifique
    Avatar de Sve@r
    Homme Profil pro
    Ingénieur développement logiciels
    Inscrit en
    Février 2006
    Messages
    12 830
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Oise (Picardie)

    Informations professionnelles :
    Activité : Ingénieur développement logiciels
    Secteur : Aéronautique - Marine - Espace - Armement

    Informations forums :
    Inscription : Février 2006
    Messages : 12 830
    Billets dans le blog
    1
    Par défaut
    Citation Envoyé par clement_74 Voir le message
    ça tourne, les fichiers sont bien lisibles et identiques aux originaux (même sans passer par mysql) et en considérant plusieurs fichiers (issus d'une liste).
    Oui, comme je te l'ai dit, je pense que c'est l'opération "binaire=>mysql" et "mysql=>binaire" qui est à vérifier.

    Citation Envoyé par clement_74 Voir le message
    #mauvaise idée... reconvertir un tel str apparait impossible..??
    Ce n'est même pas une question de str, c'est "comment savoir que fic1 s'arrête là et que f2 commence ici" (parce que là tu n'as stocké que des noms, mais tu veux stocker du contenu). Etant donné que ce n'est que du binaire (donc tout caractère posible), tu ne peux même pas dire "je place tel caractère comme séparation".
    La seule solution que j'imagine, c'est "j'écris la taille puis j'écris le fichier puis j'écris la taille puis...". A la récupération tu peux donc compter.

    Citation Envoyé par clement_74 Voir le message
    #l'idée aurait été de remplacer le "liste_pj_bin" de la liste ci-dessous (qui est une vraies liste d'objets binarisés) par "liste_from_mysql" (qui n'est finalement qu'un gros string)
    Tu peux t'intéresser à deux outils
    • pickle, qui permet de dumper un objet Python quelconque en grosse data binaire et inversement
    • base64, qui permet de convertir un truc binaire en string et inversement (mais fatalement la string est plus grosse que le binaire d'où elle vient)


    Citation Envoyé par clement_74 Voir le message
    c'est pour cette étape que le md5 est utile? pour convertir une chaine "binaire" en chaine de caractère?
    Absolument pas. Le md5 sert à signer un flux. C'est une réduction mathématique d'un flux de taille infinie en nombre fini (comme par exemple si je disais "modulo 7"). De là, le nombre "20" donne "6". Mais du seul nombre final md5 (ici 6), tu ne peux pas revenir à la data d'origine (ça peut être 6, 13, 20, 27, 34, ...)
    C'est comme une empreinte digitale. Avec le md5, tu peux vérifier que le flux récupéré correspond au flux initial mais tu ne peux pas retrouver le flux initial.
    Mon Tutoriel sur la programmation «Python»
    Mon Tutoriel sur la programmation «Shell»
    Sinon il y en a pleins d'autres. N'oubliez pas non plus les différentes faq disponibles sur ce site
    Et on poste ses codes entre balises [code] et [/code]

Discussions similaires

  1. [MySQL] Affichage Fichier JOINT (depuis table MySQL type BLOB) header content
    Par encore_php dans le forum PHP & Base de données
    Réponses: 2
    Dernier message: 01/04/2008, 16h57
  2. Réponses: 6
    Dernier message: 17/11/2005, 14h39
  3. installation mysql linux: fichier my.cnf
    Par ben23 dans le forum Installation
    Réponses: 1
    Dernier message: 24/10/2005, 13h25
  4. Envoi Mail + fichier joint
    Par mikovitch1 dans le forum C++Builder
    Réponses: 4
    Dernier message: 05/10/2005, 11h02
  5. Limiter taille fichier joint à un mail
    Par fdthierry dans le forum Applications et environnements graphiques
    Réponses: 2
    Dernier message: 27/08/2004, 12h12

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