Como subir una imagen a una base de datos usando PDO

En este artículo se va a explicar paso a paso como almacenar una imagen en formato binario en las bases de datos de Oracle, Mysql y PostgreSQL

A continuación se explicará cómo subir una imagen a una base de datos en Oracle, Mysql y PostgreSQL, (no me refiero a guardar la ruta en la base de datos y la imagen guardarla en el servidor, me refiero a guardarla directamente en nuestra base de datos).

 

Objetivos del artículo:

Para cada base de datos indicadas anteriormente (MySQL, PostgreSQL y Oracle):

Insertar una imagen en base de datos

Leer la imagen de la base de datos

– Como subir una imagen a MySQL mediante PDO

Bien, comencemos por MySQL, para comenzar tenemos que crear una tabla con los siguientes datos: archivo_id y archivo.

archivo_id: Este será la clave primaria y su función es darle un valor único a la fila que insertemos, vamos un identificador de toda la vida, para nuestra comodidad que sea autoincrement. Este campo será un int.

Archivo: aquí almacenaremos los datos binarios de la imagen. Este campo es el importante, como queremos guardar una cantidad considerable de datos binarios le asignamos el tipo BLOB.

Una vez tengamos nuestra base de datos creada podemos pasar al código.

Vamos a usar tres archivos por cada gestor de base de datos.

IndexFormulario.php : se compone de un formulario donde podremos cargar y enviar la imagen.

Enviar.php : comprobaremos si se está enviando correctamente la imagen y si es así la guardaremos en nuestra base de datos.

LeerImagen.php: leeremos la imagen desde la base de datos mediante un SELECT

Comenzaremos por IndexFormulario.php, usaremos un formulario sencillo para cargar la imagen que deseemos y mandarla a enviar.php:

 
<form enctype="multipart/form-data" action="enviar.php" method="POST">
 
Subir imagen: <input name="archivo" type="file" />
 
<input type="submit" value="Send File" />
 
</form>

 

Entramos a enviar.php para recibir la imagen

 
// archivo temporal (ruta y nombre)
 
$tmp_name = $_FILES["archivo"]["tmp_name"];
 
// Obtenemos los datos de la imagen tamaño, tipo y nombre
 
$tamano = $_FILES["archivo"]['size'];
 
$tipo = $_FILES["archivo"]['type'];
 
$nombre = $_FILES["archivo"]["name"];
 
//ruta completa
 
$archivo_temporal = $_FILES['archivo']['tmp_name'];
 
//leer el archivo(imagen) temporal en binario
 
$fp = fopen($archivo_temporal, 'r+b');
 
$data = fread($fp, filesize($archivo_temporal));
 
ob_end_clean();
 
ob_start();
 
//mostramos la imagen en nuestro explorador para comprobar que se ha cargado correctamente
 
echo $data;
 
/* en nuestro caso subiremos imágenes jpeg, pero si queremos incluir tipos diferentes deberíamos usar 
la variable $tipo definida anteriormente y sustituirla por image/jpeg que aparece en la línea de abajo */
 
header("Content-Type: image/jpeg");
 
header("Content-Disposition: inline; filename='imagen.jpg'");
 
header('Expires: 0');
 
header('Pragma: cache');
 
header('Cache-Control: private');
 
ob_end_flush ();
 
//escapar los caracteres
 
$data = mysql_escape_string($data);
 
fclose($fp);
 
//insertamos el archive binario que hemos obtenido y lo guardamos en la base de datos Mysql
 
$sql = $conn->prepare("INSERT INTO archivos (archivo_id ,archivo) VALUES('$archivo_id','$data')");
 
$sql->execute();

Ahora vamos al tercer archivo para leer la imagen, antes que nada comprobar que se ha almacenado bien directamente sobre nuestra base de datos, no se podrá ver todo el código binario ya que es muy largo, lo que muestra el campo almacenado es [BLOB – 64KB], lo que ocurre es que la imagen si es muy pesada no se cargara completamente y saldrá cortada, quizás si quieres almacenar imágenes bastante pesadas deberías escoger otro tipo más adecuado.

– Como visualizar una imagen desde MySQL mediante PDO

Vamos dentro del archivo LeerImagen.php

 
/* Realizamos una consulta sobre nuestra imagen almacenada, para ello usamos el parámetro archivo_id */
 
$query = "select archivo, tipo_imagen from archivos where archivo_id=18";
 
$stmt = $conn->prepare($query);
 
$stmt->execute();
 
//Usamos bindColumn() que se encarga vincular una variable con el resultado de la consulta
 
/* Usamos el procedimiento PDO::PARAM_LOB, esto sirve para asignarle el tipo a la variable, nosotros usaremos el tipo PARAM_LOB para guardar binarios */
 
$stmt->bindColumn(1, $data, PDO::PARAM_LOB);
 
/* FETCH_BOUND: devuelve TRUE y asigna los valores de las columnas definidas anteriormente con bindColumn*/
 
$stmt->fetch(PDO::FETCH_BOUND);
 
//le decimos el tipo de la imagen para que se visualice y la mostramos
 
header("Content-Type: image/jpeg");
 
echo $data;
– Como subir una imagen a PostgreSQL mediante PDO

El archivo IndexFormulario.php es el mismo para todos, asique pasaremos directamente al archivo enviar.php.

Veremos que es bastante parecido a MySQL ya que al usar PDO más o menos se trabaja casi igual, el más diferente es Oracle pero ese lo veremos después.

Creamos primero la tabla en la base de datos, lo único a tener en cuenta es que hay que declarar para nuestro campo archivo que será donde almacenemos nuestra imagen el tipo bytea.

 
// Archivo temporal (ruta y nombre)
 
$tmp_name = $_FILES["archivo"]["tmp_name"];
 
// Obtenemos datos
 
$tamano = $_FILES["archivo"]['size'];
 
$tipo = $_FILES["archivo"]['type'];
 
$nombre = $_FILES["archivo"]["name"];
 
$archivo_temporal = $_FILES['archivo']['tmp_name'];
 
//leer el archivo temporal en binario
 
$fp = fopen($archivo_temporal, 'r+b');
 
$data = fread($fp, filesize($archivo_temporal));
 
ob_end_clean();
 
ob_start();
 
echo $data;
 
header("Content-Type: image/jpeg");
 
header("Content-Disposition: inline; filename='imagen.jpg'");
 
header('Expires: 0');
 
header('Pragma: cache');
 
header('Cache-Control: private');
 
ob_end_flush ();
 
//escapar los caracteres
 
$data = pg_escape_bytea($data);
 
fclose($fp);
 
/*le indicamos un identificador si no hemos indicado en la base de datos que sea autoincrement */
 
$archivo_id = 15;
 
$sql = $conn->prepare("INSERT INTO archivos (archivo_id ,archivo) VALUES('$archivo_id','$data')");
 
$sql->execute();

Comprobamos que se ha guardado correctamente el campo en la base de datos, al ser binario no podrás leerlo y saldrá en su lugar

– Como visualizar una imagen desde PostgreSQL mediante PDO

Ahora nos dirigimos al archivo LeerImagen.php y comprobamos que muchas cosas son parecidas a MySQL pero no todas:

 
$conn->query("SET bytea_output=escape");
 
$query = "select archivo from archivos where archivo_id=15";
 
$stmt = $conn->prepare($query);
 
$stmt->execute();
 
$stmt->bindColumn(1, $data, PDO::PARAM_LOB);
 
$stmt->fetch(PDO::FETCH_BOUND);
 
header("Content-Type: image/jpeg");
 
// fpassthru Escribe toda la información restante de un puntero a un archivo, vuelca la imagen
 
fpassthru($data);
– Como subir una imagen a Oracle mediante PDO

El campo del archivo binario deberá de ser esta vez tipo BLOB

Entramos en el archivo Enviar.php:

// archivo temporal (ruta y nombre)
 
$tmp_name = $_FILES["archivo"]["tmp_name"];
 
// Obtener del array FILES (superglobal) los datos del binario ... nombre, tabamo y tipo
 
$tamano = $_FILES["archivo"]['size'];
 
$tipo = $_FILES["archivo"]['type'];
 
$nombre = $_FILES["archivo"]["name"];
 
$archivo_temporal = $_FILES['archivo']['tmp_name'];
 
//leer el archivo temporal en binario
 
$fp = fopen($archivo_temporal, 'r');
 
//Cuidado, lectura con +b puede traer errores en oracle en determinados casos
 
ob_end_clean();
 
ob_start();
 
ob_end_flush ();
 
$tipo = "image/jpeg";
 
$sql = <<<query
 
INSERT INTO archivos
 
(
 
ARCHIVO_ID,
 
TIPO_IMAGEN,
 
ARCHIVO
 
)
 
VALUES
 
(
 
/*le asignamos al identificador +1 para no ponerlo a mano en el caso que no tengamos autoincrement*/
 
(select max(ARCHIVO_ID)+1 from archivos),
 
EMPTY_BLOB()
 
)
 
RETURNING ARCHIVO INTO :P_ARCHIVO
 
query;
 
$stmt = $conn->prepare($sql);
 
$stmt->bindParam(':P_ARCHIVO', $fp, PDO::PARAM_LOB);
 
$conn->beginTransaction();
 
$stmt->execute();
 
$conn->commit();
– Como visualizar una imagen desde Oracle mediante PDO

Dentro del archivo leerImagen.php:

 
$sql = "SELECT ARCHIVO FROM ARCHIVOS WHERE ARCHIVO_ID = :ARCHIVO_ID";
 
/*ponemos identificador desde barra de dirección del navegador, también se podría poner de otra panera como $id = 5*/
 
$id = $_REQUEST['id'];
 
$stmt = $conn->prepare($sql);
 
$stmt->execute(array(':ARCHIVO_ID' => $id));
 
$rs = $stmt->fetch($conn::FETCH_ASSOC);
 
header("Content-Type: image/jpg");
 
//leemos la imagen, como vemos es diferente a las otras bases de datos
 
echo stream_get_contents($rs['ARCHIVO'])

No es una práctica demasiada habitual la de almacenar imágenes dentro de la base de datos, lo que se suele hacer es guardar la imagen en el servidor y en la base de datos guardarse la ruta en la que se encuentra la imagen dentro del servidor.

Iván Martínez

Ingeniero Informático apasionado por el mundo del desarrollo WEB. Me gusta caminar por este mundo lleno de tecnologías y día a día aprender cosas nuevas como el doctor Frankenstein ¡dadme cosas para experimentar!

3 comentarios sobre “Como subir una imagen a una base de datos usando PDO

Deja un comentario

Tu dirección de correo electrónico no será publicada.