Blob - Insertar y Actualizar Archivo en campo blob. Oracle, Mysql

En ocaciones nos vemos en la necesidad de guardar una imagen, un pdf, etc. en la base datos y  así mismo extraerlo, por lo tanto en esta entrada les mostraré de una forma genérica como hacerlo, el código fuente fue probado en Oracle y Mysql, trataré de probarlo en postgresql. Las versiones de los drivers en las distintas base datos son:
- Oracle: ojdbc14.jar.
- Mysql : mysql-connector-java-5.1.18-bin.jar
Cuando escribo "genérica" me refiero a no usar una clase especifica del driver correspondiente  a la base datos.
Para mostrar como hacerlo he creado un grupo de clases que son:
- Conexion: Esta clase se encarga de la parte de la conexión.
- Archivos: Esta clase contiene dos métodos escribir y obtenerArchivo, que son los encargados de escribir el archivo en la tabla y de obtener el archivo de la tabla en el orden correspondiente.
- ObtenerPropiedades: Esta clase fue creada para leer el archivo de propiedades. 
Las propiedades  contienen los datos tanto como la clase de conexión del driver y los datos necesarios de  acceso como URL, usuario, contraseña.
- PropertyException:Esta clase fue creada para manejar las excepciones si no se encuentra  alguna propiedad requerida. 
- Datosblob: Esta clase fue creada como clase principal o de ejecución. En donde para guardar  un archivo nos mostrará un ventana de selección de archivo.
Exported from Notepad++
public int escribir(String nombre, String rutaArchivo) { InputStream entrada = null; PreparedStatement pst = null; int ingresados = 0; try { File archivo; String insert; establecerConexion(); getCon().setAutoCommit(false); insert = "Insert into ARCHIVOS values(?,?)"; pst = getCon().prepareStatement(insert); archivo = new File(rutaArchivo); entrada = new FileInputStream(archivo); pst.setString(1, nombre.toUpperCase()); pst.setBinaryStream(2, entrada, (int) archivo.length()); ingresados = pst.executeUpdate(); getCon().commit(); } catch (FileNotFoundException ex) { Logger.getLogger(Archivos.class.getName()).log(Level.SEVERE, null, ex); } catch (IOException ex) { Logger.getLogger(Archivos.class.getName()).log(Level.SEVERE, null, ex); } catch (SQLException ex) { Logger.getLogger(Archivos.class.getName()).log(Level.SEVERE, null, ex); } finally { try { if (entrada != null) { entrada.close(); } } catch (IOException ex) { Logger.getLogger(Archivos.class.getName()).log(Level.SEVERE, null, ex); } try { if (pst != null) { pst.close(); } } catch (SQLException ex) { Logger.getLogger(Archivos.class.getName()).log(Level.SEVERE, null, ex); } } return ingresados; } public boolean obtenerArchivo(String nombreArchivoBuscar, String nombreArchivoSalida) { InputStream salida = null; try { PreparedStatement pst; ResultSet rs; Blob blob; FileOutputStream archivoSalida; String select; byte[] arreglo; int byteLeidos = 0; establecerConexion(); getCon().setAutoCommit(false); select = "select ARCHIVO from ARCHIVOS WHERE NOMBRE=?"; pst = getCon().prepareStatement(select); pst.setString(1, nombreArchivoBuscar); rs = pst.executeQuery(); if (rs != null) { rs.next(); blob = rs.getBlob(1); salida = blob.getBinaryStream(); arreglo = new byte[2048]; archivoSalida = new FileOutputStream(nombreArchivoSalida); while ((byteLeidos = salida.read(arreglo)) > -1) { archivoSalida.write(arreglo, 0, byteLeidos); } return true; } else { return false; } } catch (IOException ex) { Logger.getLogger(Datosblob.class.getName()).log(Level.SEVERE, null, ex); return false; } catch (SQLException ex) { Logger.getLogger(Datosblob.class.getName()).log(Level.SEVERE, null, ex); return false; } finally { try { if (salida != null) { salida.close(); } } catch (IOException ex) { Logger.getLogger(Datosblob.class.getName()).log(Level.SEVERE, null, ex); } } }
Adjunto los fuentes utilizados.


El que no ama,no ha conocido a Dios;
porque Dios es amor
1ra Juan 4:8






Descargar Fuentes

6 comentarios:

Pipe Belalcazar dijo...

Hola primero que nada te agradesco tu contribucion a la comunidad

ahora para entrar en contexto te quería decir que a la hora de realizar la insercion en la tabla la aplicacion lo hace sin ningun problema.

Pero a la hora de ir a buscar el archivo no lo encuetra o no lo puede abrir, por que mira que en la consola no me sali ningun tipo de error, es decir, al escoger la opcion 2 me sale BUILD SUCCESSFUL (total time: 13 seconds) y trata de cargar el archivo, pero no lo abre.

Tambien te queira preguntar: pues tengo entendido que el los campos de tipo BLOB guardan los archivos en la BD y no hay necesidad de colocar rutas de donde esten almacenados los archivos para hallar estos, siendo asi por que cuando escojo la opcion 2 es necesario colocar en la clase Datosblob la ruta de mi archivo mas el nombre de este mas la ext?

Te agradesco la informacion que me puedads brindar

Att
Andres Belalcazar.

Ariel O. Barria dijo...

Hola Andres, siempre que tenga tiempo trato de dar mi apoyo :)

Bueno el código que realicé no tiene ninguna línea que abra el archivo después de extraído de la base de datos, por lo tanto debes buscarlo en la ruta que le pones para que lo guarde y de ahí lo abres normalmente, si requieres que el archivo se abra, si puede hacer.

La segunda pregunta se relaciona con la respuesta de la primera, la ruta que le pones es para que lo guarde en el disco duro en la partición que le das.
Tú estarías diciendo en código lo siguiente:
Busca en la tabla ARCHIVOS por el campo archivo el blob que se encuentra ahí y luego lo escribes con este nombre que te doy en la ruta que te doy y con la extensión que te doy.

Chitin dijo...

Tu código me fue de mucha ayuda...pero tengo un problema, en mi código leo los datos de una tabla con varias columnas, una de ellas de tipo BLOB de una BD Oracle y voy generando las sentencias INSERT para todas las columnas con '' en la columna BLOB, y luego hago un UPDATE con dicha columna, ejecutándolas en una BD MySql, para pocos datos (unos 100) tarda unos pocos segundos, pero en cuanto los registros aumentan, unos 300 o más, el proceso se ralentiza en extremo y el archivo .ibd correspondiente a la tabla crece de forma desmesurada, casi 4 Gbytes y el proceso se queda atascado.

Los ficheros contenidos en los registos BLOB no alcanzan ni los 500 Mbytes.
¿Alguna idea de porqué puede suceder esto? ¿elarchivo más grande es de 22 Mbs.? he modificado el parámetro max_allowed_packet = 40M.

Muchas gracias por tu ayuda!

eduardo dijo...

ayudame con este codigo me crea el archivo en 0 bytes o sea no esta descargando el archivo verdadero aqui el codigo:
public void ver() {
Buscar bus = new Buscar();
String jo = bus.getStrResultado();
Conectar con = new Conectar();
Connection mosr = con.conexion();


try {
Statement st;
st = mosr.createStatement();
ResultSet resp = st.executeQuery("SELECT imagen FROM saliente WHERE descripcion = '"+jo+"'");
//resp.next();
String pathname ="/root/pdf_recupado.pdf";
File file = new File(pathname);
FileOutputStream output = new FileOutputStream(file);

Blob archivo = resp.getBlob(1);
System.out.println("joder ps");
InputStream inStream = archivo.getBinaryStream();
int length = -1;
int size = (int) archivo.length();

byte[] buffer = new byte[size];
while ((length = inStream.read(buffer)) != -1) {
output.write(buffer, 0, length);
// output.flush();
}
// inStream.close();
output.close();
} catch (Exception ex) {
Logger.getLogger(VenImagen.class.getName()).log(Level.SEVERE, null, ex);
}

}

Ariel O. Barria dijo...

Hola, que valor está cargando la variable size?

Anónimo dijo...

Gracias!