Bonjour à tous,
je suis débutant en Java, et je travaille actuellement sur un projet de site de commerce en ligne.
Mon projet est architecturé autour d'une base de données hsqlb et je cherche à associer chaque produit de mon site à son image.
Pour cela, lors de l'ajout d'un produit, j'ai crée un JFileChooser qui ouvre une boite de dialogue demandant d'aller chercher une image pour l'associer au produit.
Ce que je souhaite, c'est arriver à copier l'image choisie dans un répertoire de mon workspace afin que je puisse les afficher dans le site. J'arrive à copier une image à la racine de mon disque dur, mais impossible de la mettre dans le workspace.
Voici le bout de code qui effectue actuellement la copie dans un répertoire à la racine de mon disque :
JFileChooser chooser = new JFileChooser(System.getProperty("user.home")); chooser.setApproveButtonText("Open"); if(chooser.showOpenDialog(null) == JFileChooser.APPROVE_OPTION) { File f1 = chooser.getSelectedFile(); //le pb est ici je pense... File f2 = new File("/EBouffeCorp/pictures/" + f1.getName()); try{ copyFile(f1,f2); form += "copie"; } catch(Exception e){ form += "exception"; } }
La méthode copyFile() est définie plus haut et ce n'est pas là que ce situe le problème, mais bel et bien au répertoire que je fourni lors de la création de la File f2.
Comment faire donc pour lui dire de copier mon image dans un répertoire de mon workspace ??
Mon index.jsp se trouve à l'endroit par défaut (dans Web Pages) et j'aimerai mettre les images copiées dans un répertoire juste au dessus d'index.jps, dans /ress...
Merci d'avance ;-)
Si tu le dis...
... que tu fournis à copyFile...
D'abord sur quel OS est tu ? Il y a peut être déjà un problème de droits d'accès au répertoire du workspace.
Ensuite si ta méthode copyFile échoue, que ça soit de sa faute ou pas, elle doit bien de lever une exception. Qu'est-ce qu'il y a dans la trace ? Information que tu aurais du donner ici d'ailleurs.
Ensuite: /EBouffeCorp/pictures/ est censé être compris comment par Java ? Je dis bien Java hein ? Répertoire absolu ? relatif ? Si relatif, relatif à quoi ? A la racine de Tomcat ? Moi je doute que /EBouffeCorp/pictures/ corresponde bien à ce que tu veux faire. Quand je vois que tu dis " j'aimerai mettre les images copiées dans un répertoire juste au dessus d'index.jps, dans /ress...
", je doute même très fort.
Enfin, si tu me le permets, tout ça c'est du bricolage. Je veux dire copier les images pour les associer à un produit en dehors de la base de données, c'est du bricolage. Tu utilises hsqldb ? Et bien il se trouve que hsqldb supporte les blob. Donc l'approche qui s'impose est d'entrer tes images dans la base. Et ca t'évitera que ton association ne devienne très vite ingérable. AMHA.
Salut,
si j'ai dis que la méthode copyFile() était correcte, c'est qu'à priori elle fonctionne vu que je l'ai testée et qu'elle remplie bien sa fonction pour la copie à la rachine de mon disque... Là voilà néanmoins :
Par contre, j'aurai effectivement pu donner la trace de l'exception levée... Là voilà lorsque je modifie le path /EBouffeCorp/pictures (à la racine de mon disque) par le suivant : ress/products/ (qui lui se trouve dans mon workspace) :
------ java.io.FileNotFoundException: ress/products/IMAGE_TEST.png (No such file or directory) at java.io.FileOutputStream.open(Native Method) at java.io.FileOutputStream.(FileOutputStream.java:179) at java.io.FileOutputStream.(FileOutputStream.java:131) at com.EBouffeCorp.Store.TempServlet.copyFile(TempServlet.java:27) at com.EBouffeCorp.Store.TempServlet.createForm(TempServlet.java:85) at com.EBouffeCorp.Store.TempServlet.doGet(TempServlet.java:101) at javax.servlet.http.HttpServlet.service(HttpServlet.java:697) at javax.servlet.http.HttpServlet.service(HttpServlet.java:810) at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:252) at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:173) at org.jboss.web.tomcat.filters.ReplyHeaderFilter.doFilter(ReplyHeaderFilter.java:96) at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:202) at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:173) at org.apache.catalina.core.StandardWrapperValve.invoke(StandardWrapperValve.java:213) at org.apache.catalina.core.StandardContextValve.invoke(StandardContextValve.java:178) at org.jboss.web.tomcat.security.SecurityAssociationValve.invoke(SecurityAssociationValve.java:175) at org.jboss.web.tomcat.security.JaccContextValve.invoke(JaccContextValve.java:74) at org.apache.catalina.core.StandardHostValve.invoke(StandardHostValve.java:126) at org.apache.catalina.valves.ErrorReportValve.invoke(ErrorReportValve.java:105) at org.jboss.web.tomcat.tc5.jca.CachedConnectionValve.invoke(CachedConnectionValve.java:156) at org.apache.catalina.core.StandardEngineValve.invoke(StandardEngineValve.java:107) at org.apache.catalina.connector.CoyoteAdapter.service(CoyoteAdapter.java:148) at org.apache.coyote.http11.Http11Processor.process(Http11Processor.java:869) at org.apache.coyote.http11.Http11BaseProtocol$Http11ConnectionHandler.processConnection(Http11BaseProtocol.java:664) at org.apache.tomcat.util.net.PoolTcpEndpoint.processSocket(PoolTcpEndpoint.java:527) at org.apache.tomcat.util.net.MasterSlaveWorkerThread.run(MasterSlaveWorkerThread.java:112) at java.lang.Thread.run(Thread.java:613) ------
Pour répondre aux autres questions :
Je suis sur Mac OS X, mais les tests de copie que j'ai effectués à la racine du disque fonctionnaient aussi sous Windows
à priori : non (777)
et bien, je serai tenté de dire absolu, dans la mesure où la copie fonctionne très bien avec ce path, et à la racine du disque...
Ce n'est effectivement pas ce que je cherche à faire. Ce répertoire m'a servi de test pour la fonction de copie uniquement. Le but "ultime" serai d'avoir les images dans ress/products/ de mon Workspace.
Comment décrire ? En gros : dans mon Worspace j'ai un dossier Web Pages, dans lequel se trouve mon index.jsp mais également un répertoire WEB-INF (dans lequel se trouvent le web.xml et le jboss-web.xml) et le fameux répertoire "ress".
Je te le permet, il n'y a pas de souci et je ne fait que confirmer ! C'est effectivement du bricolage, mais malheureusement je n'ai pas d'excellentes connaissances en Java (mon domaine c'est plutôt le réseau à la base!!).
Je ne cherche pas à faire le projet "parfait" car malheureusement j'ai beaucoup d'autre travail et que je n'ai pas le temps pour ça. Mon but, c'est de faire quelque chose qui fonctionne et qui je soit pas trop "crade".
Oui
Dans le meilleur des monde, c'est effectivement ce que je devrai faire. Mais d'habitude je travaille plutôt sur du Oracle. L'utilisation d'hsqldb m'a été imposée, et je me rend compte qu'il y a pas mal de problèmes qui sont soulevés avec cette base.
Bien sûr son déploiement est très facile, mais je ne sais absolument pas comment importer des images dedans...
Cordialement,
Apone
Bon ben c'est très clair. Comme je n'imagine pas que IMAGE_TEST.png, ne soit pas trouvée, c'est ress qui ne l'est pas.
ress... même pas ./ress si on parle ne relatif. Tu ne mets pas les chances de ton côté.
Ah évidemment. Si tu donnes ce qui marche en disant que ça ne va pas, ça n'aide pas à t'aider...
Bon en supposant que ress_machin soit à la racine **de ton appli web** (et pas de ton disque hein ?), ce que tu sembles bien dire, depuis une page JSP ou une Servlet tu peux récupérer le répertoire racine de l'appli web ainsi:
getServletContext().getRealPath("/")
Après quoi tu concatènes avec ress_bidule et ça doit marcher comme tu le souhaites. (Oublie pas le séparateur en concaténant hein ? :D )
Qu'est-ce que les blob ont à voir avec Java ?
Welcome in Java World :D
Ca me paraît tout à fait normal de ne pas savoir ça en abordant un nouveau SGDBR. Mais je suis sûr que tu vas le trouver dans la doc :)
Et bien j'avais déjà essayé le : ./ress/products mais sans plus de succès.
Ce répertoire est effectivement à la racine de mon application web (au même niveau que l'index.jsp) et j'ai essayé un :
Voilà le répertoire que cela me retourne :
/Applications/jboss-4.0.5.GA/server/default/./tmp/deploy/tmp17555EBouffeCorp-exp.war/./ress/products/
(je suppose donc un répertoire temporaire qui est crée par JBoss à la compilation ???)
Donc lorsque je concatène avec mon répertoire puis le nom de mon fichier, je me retrouve avec :
J'ai vérifié : le fichier est bien copié dans ce répertoire, avec toutes mes autres images de mon application. C'est donc un très net progrès : j'arrive à mettre tous les fichiers d'images au même endroit...
Le problème qui se pose maintenant c'est pour l'affichage. Voilà le bout de code qui gère l'affichage de mes produits :
mais image toujours non affichée. Un clic droit sur l'image absente et voilà le path où il la cherche :
http://localhost:8080/Applications/jboss-4.0.5.GA/server/default/tmp/deploy/tmp17563EBouffeCorp-exp.war/ress/products/35.jpg
ce qui est presque correct... à un http://localhost:8080 près ...
Mais j'ai un peu cherché du côté du stockage de l'image directement dans la base.. Je suis peut être sur une piste mais c'est pas encore ça. Je vais continuer de chercher vers cet axe, ça me paraît moins laborieux et surtout moins crade que des liens vers le système de fichiers...
... affaire à suivre !
... suite de l'affaire donc ! La piste du stockage de l'image dans la base.
J'ai trouvé sur un autre forum un bout de code qui me paraît intéressant, le voici :
Si je comprend bien : la requête SQL insère dans temp_table les valeurs qui sont définie juste après, par les : statement.setString(1,name) etc... ? Le 1 et le 2 représentant les 2 points d'intérogation dans : VALUE(?,?), c'est bien ça ? Si c'est le cas, je ne connaissais pas cette méthode avec des "?"...
Partant de ça (qui est peut être faux je n'en sais rien), je dois donc créer une table "temp_table" dans laquelle je stockerai le name du produit et l'image correspondante.
Je déclare le type de ma première colonne comme une String, mais la deuxième colonne ? Comme un int ? C'est là que je coince...
Après, l'utilisation de cette méthode avec mon JFileChooser reviendrai à un simple :
insertImage(f1);
(f1 étant la File récupérée)
Ah tu travailles avec JBoss. Remarque j'aurais du m'en douter puisque JBoss embarque hsqdb. Mais comme tu parlais de déploiement de hsqldb je n'ai pas pensé à JBoss.
Bon quoi qu'il en soit: compilation de quoi :?: :D
Faute :!:
Ca c'est le chemin pour *écrire* un fichier sur le serveur. Ce n'est pa sun chemin pour servir un fichier.
Quand le navigateur client voit le lien l'image, il demande le contenu au serveur qui va chercher relativement à la racine de l'applicatino Web. donc...
... c'est parfaitement correct car tu essaies en localsur le port 8080. mais
.... c'est à toi de faire en sorte qu'il y ait
dans le lien
Autrement dit le répertoire n'est pas le même selon qu'il s'agit d'uploader ou downloader l'image :)
En effet c'est un exemple intéressant de code Java subtilement bugué.
Parce qu'il y a de grandes chances que JBoss utilise un pool de connexion.
Avec un tel code le pool peut s'épuiser très vite. Ou même sans pool le nombre de connexion simultanée permises par la bases peut être dépassé rapidement. Dans ce code tel qu'il est structuré s'il une exception se produit conn.close(); n'est jamais appelé autrement que de temps en temps par le ramasse-miette.
Sur un système chargé ça finira par bloquer.
Il faut *impérativement* structurer le comme ceci
Même, en toute rigueur il faudrait:
Hé hé qui a dit que java dispensait le programmeur de la gestion de la mémoire et des ressources :twisted:
Si ça peut te consoler, il y a plein de développeurs Java qui font cette faute :)
Disons que c'est une requête SQL préfabriquée.
Oui c'est faux. Pourquoi une table temporaire ?
Tu crées une table normale si je puis dire, et le type est un type BLOB puisque c'est de BLOB dont il s'agit. Tu vas bien voir ça dans la documentation de hsqldb
Bon, j'ai tout d'abord essayé avec les liens, plutôt que de mettre les images dans la table :
http://localhost:8080/EBouffeCorp/ress/products/35.jpg
me retourne bien une image, mais cette image pointe vers le répertoire de mon application (dans le workspace) et non sur mon système de fichiers. C'est à dire que je suis capable d'ajouter une image dans le système de fichiers avec ce path :
String imgPath = getServletContext().getRealPath("/") + "./ress/products/";
mais que je suis toujours incapable d'aller la lire avec mon application... En gros :
<img src='ress/products/35.jpg' />
et :
<img src='http://localhost:8080/EBouffeCorp/ress/products/35.jpg' />
poitent vers la même image. Il y a donc bien 2 répertoires : l'un où j'upload mon image, et l'autre où je vais la chercher...
Bref, de toute façon, même si cela marchait ce serai vraiment "crade" comme solution, donc je préfère essayer l'insertion de l'image dans la base.
J'ai corrigé le bout de code en ajoutant un bloc finally pour ma connexion, statement et stream se ferment coute que coute. J'ai également vérifié dans la doc d'HSQLDB pour voir si le type BLOB était supporté. Malheureusement HSQLDB ne semble pas supporter ce type de données :
http://hsqldb.org/doc/guide/ch09.html#datatypes-section
ce qui m'ai confirmé lorsque j'essaye de créer ma table :
CREATE TABLE temp_table(name VARCHAR(256), pic BLOB);
me retourne :
Wrong data type: BLOB in statement ....
Je pense que ce qui pourrait être "équivalent" serait de déclarer ma colonne en LONGVARBINARY, et là effectivement la table se crée.
Malheureusement, lors de l'exécution de la requête à partir de ma servlet, cela ne passe pas. Et je ne parviens pas à récupérer une trace de ce qui s'est passé. Tout ce que je sais, c'est que ma base reste ouverte et que donc le bloc finally n'a même pas été exécuté ???
Suis-je en train d'essayer d'ajouter une donnée dans ma table qui ne correspond pas au type déclaré ? Je ne pense pas. Voilà ce que me dit la javadoc pour la méthode :
statement.setBinaryStream(2, stream, (int)file.length());
Je pense donc avoir correctement déclaré le type de ma colonne pour les données à y ajouter, mais pourquoi cela ne marche t-il pas ? Cela provient-il du fait que mon stream est déclaré en FileInputStream plutôt qu'en InputStream ? J'ai essayé de changer, mais même résultat.
Je sèche et je suis pas loin d'abandonner... :(
Une image qui pointe vers un répertoire :?:
Comprenne qui pourra.
Tu devrais faire une petite pause, ça sent le surmenage là :D
Et pourquoi pas
note bien /ress et non ress
Certainement pas. Il n'y en a qu'un (il ne doit...) exprimé en absolu quand tu uploades l'image, et en relatif à la racine de l'application Web pour que le navigateur puisse la demander au serveur (aka JBoss)
Les BLOB sont supportés puisque je te le dis :)
Ou même simplement VARBINARY oui. J'ai dit que les BLOB étaient supportés pas que le type de données était dénommé "BLOB" :)
Et bien c'est tout simple. Si pas de trace, pas d'exception et si pas de finally non plus alors il est certain que le flux d'exécution est bloqué dans le bloc try, à coup sûr parce qu'il attend les octets du stream :) C'est le principe des entrées/sorties bloquantes ;) :lol:
Pourquoi le fichier de l'image ne peut-il être lu ? Je ne sais pas. Il est peut être verrouillé par un autre accès ou quelque chose comme ça. Je n'ai pas les moyens de le savoir, mais tu vas trouver :)
Sursum corda
Au fait tu connais ce lien ?
http://hsqldb.sourceforge.net/doc/src/org/hsqldb/jdbc/jdbcBlob.html
Et puis une dernière chose. Pardonne moi et surtout ne le prends pas contre toi. Je sais que ça ne va pas t'avancer, mais si tu as un peu parcouru ce forum tu sais que je n'estime pas Java et tu comprendras que je ne peux pas m'en empêcher... Donc je reprend ton premier post:
Quand même... je ne sais pas si le choix des solutions t'est imposé ou si c'est ton choix. Mais dans les deux cas je ne trouve pas que ça soit pertinent.
JBoss en plus.. et allez donc. Un conteneur d'EJB rien que ça....
Tu sais, tu aurais pris PHP, tu aurais fini il y a longtemps je pense.
Java, JBoss, un marteau pilon pour rater une mouche. Tss...
:twisted: :twisted: :twisted:
Et bien alors là... je suis à 200% d'accord avec toi !!! Seulement je n'ai pas le choix... Les outils me sont imposés, et ci ça ne tenait qu'à moi, j'aurai certainement terminé depuis longtemps... avec PHP et une bonne base MySQL !!!
hmmm......effectivement !
Je cherche encore un peu, et si je m'en sort pas, je laisserai tomber l'importation des images dans la base... Tans pis. Ce qui m'embête c'est que j'aimais bien le princie du JFileChooser...
Remets de l'ordre dans tes idées, prends un peu de recul, fais une pause, et tu vas t'en sortir. Il n'y a pas de raisons. Au point où tu en es, ce qui te bloques est certainement tout bête AMHA. Ca serait dommage d'abandonner à ce stade.
Bon bah voilà... Ca, c'est fait. On passe à autre chose. Merci quand même de ton aide.
Allons allons on se calme :)
Pourquoi crois tu que je t'ai donné le lien sur la javadoc jdbcBlob dans un post précédent en te demandant si tu connaissais ? C'est bien dans cette page qu'il est dit que setBinaryStream n'est pas implémenté ?
Tu ne penses quand même pas qu'après avoir mis un BLOB dans la base on ne puisse pas le relire ? :D
Ton tort est d'être accroché au bout de code "intéressant" et bugué que tu as trouvé je ne sais où. Pour lire les BLOB tu vas devoir écrire un peu de code personnel en utilisant la méthode getBytes.
Mais bon, si tu ne veux pas perdre de temps avec ça, pas de problème. Si la solution de l'image dans un répertoire te convient, vas-y comme ça :)
oui, en effet !
Non,non... Je me doute bien qu'il doit très certainement y avoir un moyen, c'est certain. C'est juste qu'en voyant la simplicité apparente de la gestion des blob dans une base MySQL ou PotgreSQL... Ca me décourageait un peu...
Je vais me pencher sur cette méthode, merci :) Mais maintenant il va falloir attendre jeudi... Cours obligent... et surtout interros...
Welcome in Java World
Heu je te l'ai déjà dit je crois ;)
Bon courage