3

I'm trying put an image in a MySQL database through tag <s:file> in jsp page (I'm using Struts 2):

<s:form action="carica" id="carica" style="display:none">
    <s:file id="carica" name="caricaimg"></s:file>
    <s:submit value="Carica" ></s:submit>
</s:form>

and in my Class I made this:

public String carica() throws SQLException, FileNotFoundException{
    Connessione();   // DB connection method
    System.out.print(caricaimg);
    File file = new File(caricaimg);
    InputStream fin = new java.io.FileInputStream(file);
    int fileLength = (int)file.length();
    PreparedStatement pstmt = con.prepareStatement("INSERT INTO Utenti (NomeImg, Immagine) VALUES (?, ?)");
    pstmt.setString(1, file.getName());
    pstmt.setBinaryStream (2, fin, fileLength);
    pstmt.executeUpdate();
    return "success";
}

Everything looks ok, but when I select an image with <s:file> it returns only the name of the selected file so when I try to put the image in DB it returns this error

HTTP Status 500 - ImgName.jpg (Unable to found selected file)

This is my struts.xml file

    <?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE struts PUBLIC
   "-//Apache Software Foundation//DTD Struts Configuration 2.0//EN"
   "http://struts.apache.org/dtds/struts-2.0.dtd">
<struts>
   <package name="Model" extends="struts-default">
      <action name="dati" class="Model.Registrazione" method="execute">
            <result name="success">/RegistrazioneRiuscita.jsp</result>
      </action>
      <action name="login">
            <result>/Login.jsp</result>
      </action>
      <action name="acces" class="Model.Registrazione" method="accesso">
            <result name="success">/LoginRiuscito.jsp</result>
            <result name="fail">/LoginFallito.jsp</result>
      </action>
      <action name="modifica" class="Model.Registrazione" method="modifica">
            <result name="success">/ModificaRiuscita.jsp</result>
            <result name="fail">/ModificaFallita.jsp</result>
      </action>
      <action name="elimina" class="Model.Registrazione" method="elimina">
            <result name="success">/EliminatoSuccesso.jsp</result>
      </action>
      <action name="carica" class="Model.Registrazione" method="carica">
            <result name="success">/index.jsp</result>
      </action>
      </package>
</struts>

This is the part that processes the selected file as method="POST"

<action name="carica" class="Model.Registrazione" method="carica">
    <result name="success">/index.jsp</result>
</action>
Andrea Ligios
  • 49,480
  • 26
  • 114
  • 243
Renny
  • 114
  • 10
  • 3
    You only get the filename not the path from the user's machine because that would be a security risk for the user. You don't need the path on their machine nor should you desire it...because you're going to put the file on your server wherever you want it, not where they had it. – developerwjk Dec 04 '14 at 21:26
  • Yeah, but without the path how can i give the selected file to 'File file = new File();" ? – Renny Dec 04 '14 at 21:51
  • You have to save it to the server and then you have a full path, the path to where it is on the server. You didn't post the code where you actually process the file from the POST, but it should be doing that already. If its not, there's the problem. – developerwjk Dec 04 '14 at 21:54
  • But i'm using Struts 2, i don't need to write method="POST". (I edited main question, so you can see my struts.xml file) – Renny Dec 04 '14 at 23:35
  • I was talking about the server-side part where you actually retrieve the file and save it. Where is that? For instance, the variable `caricaimg` which is apparently global, where are you setting that? – developerwjk Dec 04 '14 at 23:37
  • When in jsp page i write "" and in my Class i create a variable with the same name, that variable takes the value of s:file tag. But it gives only the name of the selected file – Renny Dec 04 '14 at 23:41
  • If the variable `caricaimg` contains the *name* of the file, then you've lost the *contents* of the file, which is my point. You are just throwing away the contents. I don't know enough about Struts to help you other than pointing that out. – developerwjk Dec 04 '14 at 23:44
  • And without struts how would you do? – Renny Dec 04 '14 at 23:56
  • Without Sturts, I'd use the Apache Commons File Upload library to parse the file out of the request object and save to disk. Then from there read the file from disk and do whatever you want with it. And, of course, `enctype="multipart/form-data"` on the form. – developerwjk Dec 04 '14 at 23:57

1 Answers1

0

Don't use the same Action file with so many actions within... it will soon become a nightmare to mantain.

BTW when you are uploading a file with Struts2, it's all automatic: the Default Interceptor Stack, that you haven't changed, uses the File Upload Interceptor to populate three variables (a File element with the file itself, not only the name, and two Strings for the fileName and the contentType) in your Actions, assuming you have the setters.

You are also missing the right enctype in your form, that for binary uploads must be multipart/form-data.

Then it should be like this:

JSP

<s:form action="carica" enctype="multipart/form-data">
    <s:file name="caricaimg" />
    <s:submit value="Carica" />
</s:form>

Action

private File caricaimg;
private String caricaimgFileName;
private String caricaimgContentType;

/* getters and setters here */

public String carica() throws SQLException, FileNotFoundException{
    Connessione();   // DB connection method
    System.out.print(caricaimg);

    // not needed -> caricaimg is already a file !!
    // File file = new File(caricaimg);
    // InputStream fin = new java.io.FileInputStream(file);
    // int fileLength = (int)file.length();

    InputStream fin = new java.io.FileInputStream(caricaimg);
    int fileLength = (int)caricaimg.length();
    PreparedStatement pstmt = con.prepareStatement("INSERT INTO Utenti (NomeImg, Immagine) VALUES (?, ?)");

    // not needed -> you already have the fileName
    // pstmt.setString(1, file.getName());

    pstmt.setString(1, caricaimgFileName);
    pstmt.setBinaryStream (2, fin, fileLength);
    pstmt.executeUpdate();

    // DON'T FORGET TO CLOSE THE STREAM !!
    fin.close();
    // ---------

    return "success";
}

Read more on this related question.

Community
  • 1
  • 1
Andrea Ligios
  • 49,480
  • 26
  • 114
  • 243
  • I found solution just one minute before your answer. BTW your modify doesn't works, i don't know why but it gives an error on this line " InputStream fin = new java.io.FileInputStream(caricaimg); " – Renny Dec 05 '14 at 00:14
  • I have to modify it, now it puts on db only the selected file and i'm using Statement instead of PreparedStatement `public String carica() throws SQLException{ Connessione(); Statement cmd = con.createStatement(); String query = "UPDATE Utenti SET Immagine = '"+caricaimg+"' WHERE Username = '"+username+"';"; cmd.executeUpdate(query); return "success"; } ` – Renny Dec 05 '14 at 00:33
  • [NO, you can't](http://stackoverflow.com/a/9430084/1654265). Also never concatenate Strings like that in a query to prevent SQL Injection. That said, the code in the answer should work fine, if you have an exception on that line, please post the exception (by editing your answer, not in the comments) instead of digressing of other, even worse solutions – Andrea Ligios Dec 05 '14 at 08:46
  • 1
    Sorry your code works, yesterday i forgot to put `enctype="multipart/form-data" ` in s:form – Renny Dec 05 '14 at 11:15