2

Here is the latest code. I wanted to try something different but I am still getting the same results.

I am using postgres DB and I created a column called file with a data type bytea. The image does get uploaded to the DB (I can see it in there when I view the table's data).

I tried it with several images. The size appears to be correct when I upload it but then it doubles in size when I download it. (which breaks the image).

Any help on why this is not working is greatly appreciated.

public void uploadImage(File image, String imageName) throws SQLException {     
    try {
        conn = connectionManager.ConnectToDb();

        String sql = "INSERT INTO images (name, file) "+ "VALUES(?,?)";
        System.out.println("your image name is " + imageName);
        System.out.println("Uploaded image name is " + image);      

        PreparedStatement stmt = conn.prepareStatement(sql);
        stmt.setString(1,imageName);

        fis = new  FileInputStream(image);
        stmt.setBinaryStream(2, fis, (int) image.length());

        System.out.println("Image SIZE = " +image.length());

        stmt.execute(); 
        conn.commit();

    } catch (SQLException e) {
        System.out.println("Could not insert into DB");
        e.printStackTrace();        
    } catch (FileNotFoundException e) {
            System.out.println("Could not insert into DB");
            e.printStackTrace();
    } 
     finally {
        //close DB Objects
        try {
            fis.close();
        } catch (IOException e) {
            e.printStackTrace();
        }
        conn.close();
    }
}

public void downloadImageFromDB(String imagename) throws SQLException
{
    ConnectionManager connectionManager = new ConnectionManager();

    try {
        conn = connectionManager.ConnectToDb();
        Statement downloadImageStatement = conn.createStatement();
        downloadImageStatement.executeQuery("SELECT file FROM images WHERE name = '"+imagename+"'");
        ResultSet rs = downloadImageStatement.getResultSet();
        int i=1;
        InputStream in = null;
        int returnValue = 0;

        if(rs.next())
        {
            String len1 = rs.getString("file");
            int len = len1.length();
            byte [] b = new byte[len];
            in = rs.getBinaryStream("file");
            int index = in.read(b, 0, len);
            OutputStream outImej = new FileOutputStream("C:\\EclipseProjects\\StrutsHelloWorld\\"+imagename+".JPG");

            while (index != -1)
            {
            outImej.write(b, 0, index);
            index = in.read(b, 0, len);
            System.out.println("==========================");
            System.out.println(index);
            System.out.println(outImej);
            System.out.println("==========================");
            }
            outImej.close();
        }else
            {
            returnValue = 1;
            }

        downloadImageStatement.close();
        conn.close();

    } catch (SQLException e) {
        System.out.println("Could not get image from DB");
        e.printStackTrace();
    } catch (IOException e) {
        // TODO Auto-generated catch block
        e.printStackTrace();
    } 
    finally
    {
      // close db objects.
        conn.close();
    }
    //return imgData;
}
Joachim Sauer
  • 302,674
  • 57
  • 556
  • 614
Biggs
  • 141
  • 4
  • 10
  • What does the DDL of your image table look like? – DerMike Oct 07 '10 at 14:33
  • How big is the file that is written? (`InputStream.available(...)` sometimes returns estimates) – DerMike Oct 07 '10 at 14:37
  • Is the size reported by `is.available()` always twice the first size of the image, or is it always 8000? I would test this with another image to find out if the incorrect image size just happens to be twice the expected size in this case. – matt b Oct 07 '10 at 14:39
  • Why are you storing an image in a `String` in the first place? A `String` is a data type for textual data, and if you store binary data in it, you've already made a mistake at that point. – Joachim Sauer Oct 07 '10 at 14:51
  • Here is the latest code: I wanted to try something slightly different...but I still get the same results: – Biggs Oct 07 '10 at 16:16
  • Why do you insist on using String for binary data? Again you call `rs.getString("file")` which is wrong, if you want to handle binary data. Even (and especially) if you "only" use it to get the length. – Joachim Sauer Oct 08 '10 at 12:01

3 Answers3

4

You are storing your binary data into a Unicode text field. Change your file column to binary and it should work.

Gabe
  • 84,912
  • 12
  • 139
  • 238
  • I am using postgresql. The column file data type is bytea – Biggs Oct 07 '10 at 14:47
  • Biggs: Have you looked at the file generated by `fos`? How long is it? How does its contents compare to the original file? – Gabe Oct 07 '10 at 15:36
3

You don't want to use InputStream.available() to measure its size. Here's a Q&A that describes what available() actually does - in short, not much that's useful.

One (correct) way to get the actual size is to check the size of the File after you've written to it, using File.length().

Community
  • 1
  • 1
Matt Ball
  • 354,903
  • 100
  • 647
  • 710
1

I used the latest version of JDBC driver and the problem was solved. I am using PostgreSQL 9.0.2 and the JDBC4 driver 9.0-801.

Jamir
  • 11
  • 1