La manipulación de objetos bianrios grandes (BLOB) en Oracle Data base requiere una coordinación precisa entre el sistema de archivos del servidor y la lógica de base de datos. A continuación, se presenta un flujo técnico para importar archivos de imagen directamente desde el servidor y su posterior recuperación mediante una aplicación Java.
1. Preparación del entorno en el servidor
Para que la base de datos pueda acceder a archivos físicos, estos deben residir obligatoriamente en el almacenamiento local del servidor de Oracle. Una vez ubicado el archivo, es necesario definir un objeto DIRECTORY en la base de datos:
-- Creación del directorio con sensibilidad a mayúsculas
CREATE OR REPLACE DIRECTORY STORAGE_DIR AS '/var/lib/oracle/images';
Es importante recordar que si el nombre del directorio se define entre comillas dobles, se deberá respetar exactamente el mismo formato en las llamadas posteriores de PL/SQL.
2. Inserción del archivo mediante PL/SQL
El siguiente procedimiento utiliza el paquete DBMS_LOB para cargar el contenido binario de un archivo externo en una columna de tipo BLOB.
-- Estructura de la tabla de ejemplo
CREATE TABLE repos_imagenes (
id_archivo NUMBER PRIMARY KEY,
contenido_binario BLOB,
nombre_original VARCHAR2(100)
);
-- Bloque PL/SQL para la carga de datos
DECLARE
v_bfile BFILE;
v_blob BLOB;
v_nombre VARCHAR2(50) := 'foto_perfil.jpg';
BEGIN
INSERT INTO repos_imagenes (id_archivo, contenido_binario, nombre_original)
VALUES (1, EMPTY_BLOB(), v_nombre)
RETURNING contenido_binario INTO v_blob;
v_bfile := BFILENAME('STORAGE_DIR', v_nombre);
DBMS_LOB.FILEOPEN(v_bfile, DBMS_LOB.FILE_READONLY);
DBMS_LOB.LOADFROMFILE(v_blob, v_bfile, DBMS_LOB.GETLENGTH(v_bfile));
DBMS_LOB.FILECLOSE(v_bfile);
COMMIT;
END;
/
3. Extracción y guardado con Java (JDBC)
Para recuperar la imagen y escribirla en un archivo local desde una aplicación Java, se recomienda el uso de bloques try-with-resources para garantizar que los flujos de datos se cierren correctamente.
import java.io.*;
import java.sql.*;
public class ExtractorImagenes {
public void descargarImagen(int id) {
String dbUrl = "jdbc:oracle:thin:@localhost:1521:xe";
String sql = "SELECT contenido_binario FROM repos_imagenes WHERE id_archivo = ?";
try (Connection conn = DriverManager.getConnection(dbUrl, "usuario", "password");
PreparedStatement pstmt = conn.prepareStatement(sql)) {
pstmt.setInt(1, id);
try (ResultSet rs = pstmt.executeQuery()) {
if (rs.next()) {
Blob blobData = rs.getBlob("contenido_binario");
File destino = new File("C:/temp/imagen_descargada.jpg");
try (InputStream input = blobData.getBinaryStream();
FileOutputStream output = new FileOutputStream(destino)) {
byte[] buffer = new byte[8192];
int bytesLeidos;
while ((bytesLeidos = input.read(buffer)) != -1) {
output.write(buffer, 0, bytesLeidos);
}
System.out.println("Archivo guardado exitosamente en: " + destino.getAbsolutePath());
}
}
}
} catch (SQLException | IOException e) {
e.printStackTrace();
}
}
}
Consideraciones técnicas adicionales
- Entornos Virtualizados: Si Oracle se ejecuta en un contenedor (como Docker), la ruta definida en el
DIRECTORYdebe ser una ruta interna del contenedor. Los montajes de volúmenes de red o carpetas compartidas deben estar correctamente mapeados para que el motor de la base de datos tenga permisos de lectura sobre ellos. - Consultas en Herramientas de Administración: Al ejecutar un
SELECTsimple sobre una columna BLOB en herramientas como SQL Developer, generalmente solo se visualiza el tamaño del objeto o un puntero de referencia, no los datos binarios completos. - Optimización de Memoria: El uso de un buffer (como
byte[8192]) en Java es fundamental para manejar archivos de gran tamaño sin saturar la memoria RAM de la aplicación.