Subir campos Blob a BBDD (Oracle) con Java

Hay veces que queremos subir un archivo a un campo blob de una tabla.... (mas recomendable es dejar el archivo en un servidor y solo almacenar la ruta, pero hay veces que por narices hay que hacerlo asi....asi que voy a explicar como hacerlo.

Vamos a hacer un programa que lea un archivo , lo pase a un array de bytes y luego lo inserte en la tabla.

Este programa lo que hace es UPDATE del campo Blob en un registro de una tabla que ya existe.
Asi que es necesario que exista el row en la tabla, con el campo blob (ya sea vacio o no).

Importante: necesitas la libreria con el driver jdbc para oracle (ojdbc6.jar)

1.Lo primero necesitamos un metodo que lea un archivo y lo pase a array de Bytes:
import java.io.ByteArrayInputStream;
import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.PreparedStatement;

import oracle.jdbc.OracleResultSet;
import oracle.sql.BLOB;



    public byte[] getBytesFromFile(File file) throws IOException {
        InputStream is = new FileInputStream(file);

        // Get the size of the file
        long length = file.length();

        // You cannot create an array using a long type.
        // It needs to be an int type.
        // Before converting to an int type, check
        // to ensure that file is not larger than Integer.MAX_VALUE.
        if (length > Integer.MAX_VALUE) {
            // File is too large
        }

        // Create the byte array to hold the data
        byte[] bytes = new byte[(int)length];

        // Read in the bytes
        int offset = 0;
        int numRead = 0;
        while (offset < bytes.length
               && (numRead=is.read(bytes, offset, bytes.length-offset)) >= 0) {
            offset += numRead;
        }

        // Ensure all the bytes have been read in
        if (offset < bytes.length) {
            throw new IOException("Could not completely read file "+file.getName());
        }

        // Close the input stream and return bytes
        is.close();
        return bytes;
    }


2.Ahora necesitamos otro metodillo que conecte con nuestra BBDD. Lo vamos a hacer por JDBC:

    public Connection getConnection(){
       
        System.out.println("Getting Jdbc connection...");
        Connection connection = null;
        try {
           
            Class.forName("oracle.jdbc.OracleDriver").newInstance();
            connection = DriverManager.getConnection("jdbc:oracle:thin:@ora:1980:BBDD1", "user1", "password1");
           
            System.out.println("Connection established Succes !");

        } catch (Exception e) {
            e.printStackTrace();
        }
        return connection;
    }


3.Necesitamos un metodo que consulte la bbdd y busque la tupla en la tabla para poder hacer un "select for update" y asi poder actualizar el campo blob.
A este metodo (ya que estamos) , le vamos a pasar el archivo que queremos actualizar.
Si te fijas, veras como hacemos una consulta normal a la bbdd con el id del row que queremos actualizar ,luego hacemos el select for update y luego le enchufamos el array de bytes, es muy sencillo:

Genera el file a partir de la ruta que le pasamos, hace el select for update y ya esta.
(vemos que la conexion la coge llamando a getConnection(), y el array lo consigue del otro metodo que pusimos antes)

    public void doUpdateBlob( String idRow, String archivo) throws Exception{
        //Transforma a bytes el archivo
        byte[] fileByteArray = getBytesFromFile(new File(archivo));
        //Prepara el registro para hacer el update. llama a getConnection() para la conexion
        PreparedStatement ps  = getConnection().prepareStatement(
            "SELECT BLOB_FIELD FROM TABLA1  " +
            "    WHERE ID_REGISTRO = ? for update");
        ps.setInt(1,Integer.parseInt(idRow));
        OracleResultSet rs = (OracleResultSet) ps.executeQuery();
        boolean found = false;
        if (rs.next()) {
            found = true;
            BLOB blob = (BLOB) rs.getBLOB(1);
            OutputStream outputStream = blob.setBinaryStream(0L);
            InputStream inputStream = new ByteArrayInputStream(fileByteArray);
            byte[] buffer = new byte[blob.getBufferSize()];
            int byteread = 0;
            while ((byteread = inputStream.read(buffer)) != -1) {
                outputStream.write(buffer, 0, byteread); //mete el archivaco en el buffer
            }
            outputStream.close();
            inputStream.close();
        }
       
        if(!found){
            System.out.println("ERROR , No se encuentra el registro en la tabla.");
        }
    }


4. Ahora el metodo general que lanzara todo el proceso:

    public void subemeElBlob(){
        try {
            String rutaArchivo = "c:"+File.separator+"arhivoAsubir.jpg";
            String idRegistro = "23";
       
            doUpdateBlob(idRegistro, rutaArchivo);//haciendo el trabajo
       
        } catch (Exception e) {
            e.printStackTrace();
        }
    }



Si has utilizado el jar para oracle ojdbc6.jar y java (jdk) superior o igual  java 5, te deberia haber funcionado. Espero que si!!


Comentarios

  1. muy buen aporte, gracias por tu ayuda

    ResponderEliminar
  2. excelente apote, saludos desde El Salvador

    ResponderEliminar
  3. muy bueno.... pero para que es ps.setInt(1,Integer.parseInt(idRow));

    ResponderEliminar
    Respuestas
    1. Si te fijas en realidad primero haces un select del registro que quieres actualizar metiendo el blob, por eso necesitas pasarle el id (que es el que hace esa línea)

      Eliminar
    2. ok entendido, no habia interiorizado bien, sucede que mi id es un string entonces no tendo necesidad de parsear a int, pero hermano si me pudieras ayudar, sucede que me da error en la linea:OutputStream outputStream = blob.setBinaryStream(0L);

      Eliminar
    3. Si te da error ahi, lo mas seguro es que la tabla no tiene un campo Blob. ¿es asi? ¿Que base de datos usas?

      Eliminar
    4. y he comprobado que el campo sea de tipo BLOB y me sigue tirando el error que comente, Por fa... ayuda, es que debo evaluarme en eso

      Eliminar

Publicar un comentario

Entradas populares de este blog

Reiniciar usuario de SVN Subversion

Persistencia con EclipseLink 2.0