convert file or byte[] into BLOB in JAVA

Ablia :

I'm sending a file frome a client to a server and receive it like this:

            //Receive File:
            FileOutputStream fis = new FileOutputStream("receivedTest");
            DataInputStream dis = new DataInputStream(clientSocket.getInputStream());
            int count;
            byte[] buffer = new byte[4096];
            while ((count = dis.read(buffer)) > 0)
            {
              fis.write(buffer, 0, count);
            }
            fis.close();

Just like it's explained in this subject. It's working well. But the fact is, i don't really want to receive the file itself; i want a BLOB. I've read that a BLOB is just like a byte[].

In my database class (i use SQLite), i have the following table:

    String sqlFile = "CREATE TABLE IF NOT EXISTS files (\n"
            + " id integer PRIMARY KEY,\n"
            + " shorthash byte[],\n"
            + " filename text NOT NULL,\n"
            + " file blob,\n"
            + " owner text\n"
            + ");";

and the following function to insert a new "file":

public void insertFile(byte[] shorthash, String filename, byte[] file, String owner) {
    String sql = "INSERT INTO files(shorthash,filename, file, owner) VALUES(?,?,?,?)";

    try (Connection conn = DriverManager.getConnection(url);
            PreparedStatement pstmt = conn.prepareStatement(sql)) {
        pstmt.setBytes(1, shorthash);
        pstmt.setString(2, filename);
        pstmt.setBytes(3, file);
        pstmt.setString(4, owner);
        pstmt.executeUpdate();
    } catch (SQLException e) {
        System.out.println(e.getMessage());
    }
}

As you can see, there's 4 columns, the file itself is in the 3rd column. In the table it's declared as a BLOB, but when i insert it i'm just doing a setBytes. I'm not sure if this is right, it's just what i've found on internet.

So, i'm receiving this file on my server, and i want to store it in my database. If possible, i would like to avoid creating the file on server side (the line FileOutputStream fis = new FileOutputStream("receivedTest"); in my first code). I would like to store it directly in the database, since i receive it as a byte array i think it'll be easier this way.

But i don't know how to do that. Probably because i don't really understand the link between Blob and byte[]. I mean, a byte array may be too little to hold an entire file; but a blob is ok. however, to insert the file in database, i insert a byte array. This make nonsens to me.

EDIT:

So, i've tried two things: first, adding the file in the DB as it's done here (and pretty much everywhere i looked, it's always done that way):

//Receive encrypted File:
            FileOutputStream fos = new FileOutputStream("receivedTest");
            DataInputStream dis = new DataInputStream(clientSocket.getInputStream());
            int count;
            byte[] buffer = new byte[4096];
            while ((count = dis.read(buffer)) > 0)
            {
              fos.write(buffer, 0, count);
            }
            fos.close();

            DB.insertFile(shorthash, "test", "receivedTest", user);

//Insert file in DB:
public void insertFile(byte[] shorthash, String filename, String filepath, String owner) throws FileNotFoundException {
    String sql = "INSERT INTO files(shorthash, filename, file, owner) VALUES(?, ?, ?, ?)";
    try (Connection conn = DriverManager.getConnection(url);
            PreparedStatement pstmt = conn.prepareStatement(sql)) {
        pstmt.setBytes(1, shorthash);
        pstmt.setString(2, filename);

        File file = new File(filepath);
        FileInputStream   fis = new FileInputStream(file);
        pstmt.setBinaryStream(3, fis, (int) file.length());
        pstmt.execute();
        pstmt.setString(4, owner);
        pstmt.executeUpdate();
        fis.close()
    } catch (SQLException e) {
        System.out.println(e.getMessage());
    }
}

Second, insert the file as a byte array (but that won't work for big files) as it's explained in SQLite Tutorial :

//Insert file in DB:
public void insertFile(byte[] shorthash, String filename, String filepath, String owner) throws FileNotFoundException {
    String sql = "INSERT INTO files(shorthash, filename, file, owner) VALUES(?, ?, ?, ?)";
    try (Connection conn = DriverManager.getConnection(url);
            PreparedStatement pstmt = conn.prepareStatement(sql)) {
        pstmt.setBytes(1, shorthash);
        pstmt.setString(2, filename);

        File file = new File(filepath);
        FileInputStream   fis = new FileInputStream(file);    
        byte[] buffer = new byte[1024];
        ByteArrayOutputStream bos = new ByteArrayOutputStream();
        for (int len; (len = fis.read(buffer)) != -1;)
            bos.write(buffer, 0, len);
        fis.close()
        pstmt.setBytes(3, bos.toByteArray());
        pstmt.execute();
        pstmt.setString(4, owner);
        pstmt.executeUpdate();
    } catch (SQLException e) {
        System.out.println(e.getMessage());
    } catch (IOException e) {
        // TODO Auto-generated catch block
        e.printStackTrace();
    }
}

Then, when i print my DB, there is no file in it. Same if i try to open the DB with DB Browser. The console only say:

Connection to SQLite has been established. 
ouverture du server
Clients:

1   admin   admin

Files:
Ablia :

I've managed to find out a way; it's still not optimal, but it's enough for me and it probably can be usefull for others.

To save the file directly in the DB, without creating the file on server side, you can insert it as a BinaryStream. However, the method setBinaryStream take 3 inputs: the parameter index (int), the input stream, and the length of the stream. So to do so, you have to know the length of your file.

Since the client is sending the file, i just ask him to send the length of the file before with:

dout.writeInt((int) file.length());

then on server side my DataInputStream receive the length of the file, immediatly followed by the file:

//receive file size (needed to save it as inputStream in DB) and file:
            DataInputStream dis = new DataInputStream(clientSocket.getInputStream());
            int fileLength = dis.readInt();

            DB.insertFile(shorthash, filename, dis, fileLength, user);

Insert file method:

public void insertFile(String filename, InputStream fis, int length, String owner){
    String sql = "INSERT INTO files(filename, file, owner) VALUES(?, ?, ?)";
    try (Connection conn = DriverManager.getConnection(url);
            PreparedStatement pstmt = conn.prepareStatement(sql)) {
        pstmt.setString(1, filename);
        pstmt.setBinaryStream(2, fis, length);
        pstmt.setString(3, owner);
        pstmt.executeUpdate();
    } catch (SQLException e) {
        System.out.println(e.getMessage());
    }
}

Guess you like

Origin http://43.154.161.224:23101/article/api/json?id=117057&siteId=1