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

 Java Discussion :

Enregistrer facilement une image avec JDBC


Sujet :

Java

  1. #1
    Modérateur

    Homme Profil pro
    Développeur java, access, sql server
    Inscrit en
    Octobre 2005
    Messages
    2 713
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Val de Marne (Île de France)

    Informations professionnelles :
    Activité : Développeur java, access, sql server
    Secteur : Industrie

    Informations forums :
    Inscription : Octobre 2005
    Messages : 2 713
    Par défaut Enregistrer facilement une image avec JDBC
    Bon c'est une question concernant à la fois JDBC et la classe Image.
    Je veux enregistrer un objet Image dans une base via JDBC.
    Il y a des dizaines de tuto pour enregistrer par exemple un fichier JPEG dans une base MySql,
    mais j'ai eu un mal de chien à trouver quelque chose pour enregistrer un objet de la classe Image dans une base.

    Voilà ce que j'ai finalement fait :
    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
                Image img = ....
                // transformer l'image en BufferedImage
                BufferedImage bufferedImage = new BufferedImage(
                        img.getWidth(null),
                        img.getHeight(null),
                        BufferedImage.TYPE_INT_RGB );
     
                // ouverture d'un ByteArrayOutputStream dans lequel on écrit la BufferedImage
                ByteArrayOutputStream byteArrayOutputStream = new ByteArrayOutputStream();
                ImageIO.write(bufferedImage, "jpg", byteArrayOutputStream);
     
                // conversion du ByteArrayOutputStream en tableau de bytes placé dans un InputStream
                byte[] bytes = byteArrayOutputStream.toByteArray();
                ByteArrayInputStream bais = new ByteArrayInputStream(bytes);
     
                // enfin on peut écrire tout le bouzingue dans le PreparedStatement
                PreparedStatement ps = ...
                ps.setBinaryStream(1, bais, bytes.length);
    Cela fonctionne.
    Cependant existe-t-il un moyen plus simple que d'utiliser la méthode setBinaryStream qui exige de transformer l'image en InputStream de façon assez lourdingue.
    Labor improbus omnia vincit un travail acharné vient à bout de tout - Ambroise Paré (1510-1590)

    Consulter sans modération la FAQ ainsi que les bons ouvrages : http://jmdoudoux.developpez.com/cours/developpons/java/

  2. #2
    Expert éminent
    Avatar de tchize_
    Homme Profil pro
    Ingénieur développement logiciels
    Inscrit en
    Avril 2007
    Messages
    25 482
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 46
    Localisation : Belgique

    Informations professionnelles :
    Activité : Ingénieur développement logiciels
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Avril 2007
    Messages : 25 482
    Par défaut
    l'objet 'Image' de java est destiné à ton interface graphique, il n'est pas destinée à être stocké dans une base de donnée ou sous tout forme de support. Donc la solution "propre" c'est de stocker dans le db le fichier qui a servi à générer le Image.

  3. #3
    Modérateur

    Homme Profil pro
    Développeur java, access, sql server
    Inscrit en
    Octobre 2005
    Messages
    2 713
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Val de Marne (Île de France)

    Informations professionnelles :
    Activité : Développeur java, access, sql server
    Secteur : Industrie

    Informations forums :
    Inscription : Octobre 2005
    Messages : 2 713
    Par défaut
    Merci Tchize_

    C'est que justement, l'image ne vient pas d'un fichier mais a été constituée par des copiers / colés dans un JPanel ...
    De même, j'ai des JTextFields dont le contenu est enregistré en même temps dans la base (Derby ... c'est une petite application).

    Effectivement, je peux commencer par sauvegarder l'image dans un fichier et bénéficier facilement après d'un FileInputStream.
    Mais cela me semblait un détour étonnant ...
    Enfin bon, le but de ce post est juste de savoir s'il existe une meilleure solution ou bien une API déjà au point qui ferait ce travail.
    Labor improbus omnia vincit un travail acharné vient à bout de tout - Ambroise Paré (1510-1590)

    Consulter sans modération la FAQ ainsi que les bons ouvrages : http://jmdoudoux.developpez.com/cours/developpons/java/

  4. #4
    Expert éminent
    Avatar de tchize_
    Homme Profil pro
    Ingénieur développement logiciels
    Inscrit en
    Avril 2007
    Messages
    25 482
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 46
    Localisation : Belgique

    Informations professionnelles :
    Activité : Ingénieur développement logiciels
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Avril 2007
    Messages : 25 482
    Par défaut
    le code que tu as donné est tout à fait correct. Mis à part que j'éviterais un format à compression destructive comme jpg pour préférer le png, question de gout. Je ne vois pas à quoi d'autre tu t'attendais, comme je l'ai dit, les composants graphiques ne sont pas destiné à être stockés tels quel. Pour un JTextField, tu récupère sont texte avec getText(), pour une image, tu récupère ses données via ImageIO. Tu pourrais bien sur aussi récupérer directement les bytes via BufferedImage.getRaster().getDatabuffer().getOffsets(), mais tu souffrirais pour reconstituer l'image avec ça par la suite.

    Quand à trouver une api qui t'évite d'écrire 5 lignes de code :/ Je vois pas l'intérêt par rapport au fait de coder toit même la méthode

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
                PreparedStatement ps = ...
                Image img = ....
     
     
                BufferedImage bufferedImage = new BufferedImage(
                        img.getWidth(null),
                        img.getHeight(null),
                        BufferedImage.TYPE_INT_RGB );
                bufferedImage.createGraphics().drawImage(img,null,null)
                ByteArrayOutputStream baos = new ByteArrayOutputStream();
                ImageIO.write(bufferedImage, "png", baos);
                ps.setBytes(1, baos.toByteArray());

  5. #5
    Modérateur

    Homme Profil pro
    Développeur java, access, sql server
    Inscrit en
    Octobre 2005
    Messages
    2 713
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Val de Marne (Île de France)

    Informations professionnelles :
    Activité : Développeur java, access, sql server
    Secteur : Industrie

    Informations forums :
    Inscription : Octobre 2005
    Messages : 2 713
    Par défaut
    Merci de ton avis.

    trouver une api qui t'évite d'écrire 5 lignes de code :/ Je vois pas l'intérêt
    En effet !
    Je vais essayer aussi la variante que tu proposes ... et clore la discussion.
    Labor improbus omnia vincit un travail acharné vient à bout de tout - Ambroise Paré (1510-1590)

    Consulter sans modération la FAQ ainsi que les bons ouvrages : http://jmdoudoux.developpez.com/cours/developpons/java/

  6. #6
    Expert confirmé
    Avatar de sinok
    Profil pro
    Inscrit en
    Août 2004
    Messages
    8 765
    Détails du profil
    Informations personnelles :
    Âge : 45
    Localisation : France, Paris (Île de France)

    Informations forums :
    Inscription : Août 2004
    Messages : 8 765
    Par défaut
    A noter toutefois que le stockage d'images en base de données n'est pas une des pratiques des plus recommandables.

    En effet une base de données est avant tout faite pour stocker des informations, pas de la donnée non porteuse de sens immédiat, en effet difficile de poser une condition sur un champ de type blob...
    De plus les blobs posent des problèmes au niveau réactivité du SGBD qui doit bien plus mouliner pour retrouver ses données, car ils augmentent amplement la taille des éléments de stockage. Donc enregistrer des images en BDD est en général suboptimal comme solution.
    Pour celà mieux vaut utiliser un FileSystem qui est bien plus scalable de ce point de vue là et garder une référence sur l'image dans la base (nom+emplacement relatif éventuellement, même si en général on planque tout dans un répertoire spécifique.). De plus cette solution est bien plus performante dans l'ensemble (temps réseau moindre, I/O sgbd moindres, code tout aussi long, enfin bref...)

  7. #7
    Expert éminent
    Avatar de tchize_
    Homme Profil pro
    Ingénieur développement logiciels
    Inscrit en
    Avril 2007
    Messages
    25 482
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 46
    Localisation : Belgique

    Informations professionnelles :
    Activité : Ingénieur développement logiciels
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Avril 2007
    Messages : 25 482
    Par défaut
    heu un bémol quand même sinok. Stocker sur le filesystem a un effet contraire: tu désolidarise ton image du reste des données auxquelles elle est liée. Même si effectivement on ne peux pas poser de condition sur un blob, ça n'en reste pas moins une donnée liée au row. Si je stocke l'image sur le filesystem:

    -> le jour ou je fais un delete du row (delete from latable where "entrée plus vieille que 3 ans" par exemple), l'image reste sur le filesystem
    -> Je peux effacer l'image du filesystem sans savoir qu'elle est liée à un row
    -> Mes backups du filesystem ne sont pas nécessairement synchrones avec celui de la database -> en cas de restore on va se retrouver avec des inconsistance
    -> Si plusieurs connections à la DB depuis des hotes différents, tous les hotes devraient aussi avoir accès au filesystem considéré.
    -> Pour éviter des fichier "foireux" sur le filesystem, il faut inclure l'écriture du fichier dans la transaction DB (suppression en cas de rollback, isolation au niveau de la visiblité, unicité etc à gérer), ce qui nécessite en java la mise en place de XATransactions et n'est pas vraiment une mince affaire


    Pour moi, stocker une image, quand elle est liée à d'autres données, dans une DB c'est une bonne chose, et une bonne DB ne "mouline" pas tant que ça pour retrouver le blob, en général elle stock un pointeur dans la table et le blob, ainsi, n'encombre pas.
    Quand au performance, en suivant ta logique, on peux encore en gagner en n'utilisant la DB pour rien (encore moins d'IO tiens)

  8. #8
    Modérateur

    Homme Profil pro
    Développeur java, access, sql server
    Inscrit en
    Octobre 2005
    Messages
    2 713
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Val de Marne (Île de France)

    Informations professionnelles :
    Activité : Développeur java, access, sql server
    Secteur : Industrie

    Informations forums :
    Inscription : Octobre 2005
    Messages : 2 713
    Par défaut
    @Tchize

    Je viens d'essayer ton code.
    Il marche nettement mieux que le mien qui me faisait
    parfois des images "noires" sans que j'en trouve la cause.

    Maintenant le petit conte du père Népomucène avant d'aller dormir :

    En ce qui concerne le stockage d'images dans une BD, ma religion était celle de Sinok :
    je considérai la chose comme dangereuse pour les performances.
    Mais c'était du temps où je programmais en Access 2 au cours du précédent millénaire !
    (vous n'avez pas connu vous étiez trop petits )
    ... et stocker des images dans une BD Access était un bon moyen de tout casser.

    Donc sans tenir compte des évolutions techniques, pendant ces 10 dernières années j'ai sagement fait comme Sinok :
    un répertoire dédié pour les images et on enregistre uniquement le chemin...
    ... avec toutes la gamme d'ennuis évoqués par Tchize.

    Il se trouve qu'il y a quelques mois, un client m'a demandé une appli qui, entres autres,
    doit enregistrer 210.000 images jpg de 250 Mo dans une base MySQL.
    Je craignais le pire mais le test de monté en charge m'a donné une base de 32Go avec des performances tout à fait correctes.

    Du coup mon avis a changé. Je pense qu'on peut stocker de grandes quantités d'images dans une BD à condition de prendre quelques précautions.
    Dans mon cas, j'ai fait une table dédiée au stockage des photos avec une clé primaire numérique.
    J'ai donc l'intégrité référentielle entre les enregistrements "textes" et les photos
    et ma base est toujours cohérente.

    ... merci à tous les deux pour vos remarques.
    Labor improbus omnia vincit un travail acharné vient à bout de tout - Ambroise Paré (1510-1590)

    Consulter sans modération la FAQ ainsi que les bons ouvrages : http://jmdoudoux.developpez.com/cours/developpons/java/

  9. #9
    Expert éminent
    Avatar de tchize_
    Homme Profil pro
    Ingénieur développement logiciels
    Inscrit en
    Avril 2007
    Messages
    25 482
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 46
    Localisation : Belgique

    Informations professionnelles :
    Activité : Ingénieur développement logiciels
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Avril 2007
    Messages : 25 482
    Par défaut
    pour info, on gère là ou je suis une DB qui pèse plusieurs Teras au dernières nouvelles Alors quand je dois mettre 2Gs de données dans des blobs, je me pose pas vraiment de questions

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

Discussions similaires

  1. Sauvegarder une image avec la fenêtre 'Enregistrer Sous'
    Par BriocheNC dans le forum Langage
    Réponses: 5
    Dernier message: 18/05/2011, 20h57
  2. Réponses: 0
    Dernier message: 28/03/2011, 09h48
  3. Rechercher une image avec son numéro d'enregistrement
    Par b.bilel dans le forum Bases de données
    Réponses: 7
    Dernier message: 11/05/2008, 22h00
  4. Enregistrer une image avec IE
    Par fichtre! dans le forum VBScript
    Réponses: 2
    Dernier message: 16/03/2007, 21h22
  5. Enregistrement d'une image avec Firefox
    Par Eusebius dans le forum Applications et environnements graphiques
    Réponses: 9
    Dernier message: 05/07/2006, 11h22

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