Generalmente, cuando subimos un archivo de imagen en PHP, la imagen subida se almacena en un directorio del servidor y almacenamos el nombre del archivo en la base de datos. Pero, ¿qué pasa si queremos subir una imagen si guardarla en el servidor? Pues que podemos almacenarla también en la base de datos. Si te preocupa el espacio que ocupas en el servidor y necesitas liberar algo de contenido, puedes almacenar un archivo de imagen en la base de datos sin necesidad de guardarlo en un directorio del servidor. Este procedimiento ayuda a optimizar el espacio del servidor ya que el archivo se almacenará en una base de datos, y no en el propio servidor.
En este tutorial, te mostraré cómo almacenar una imagen en una base de datos MySQL, y también a recuperarla mediante PHP. No te preocupes, ya verás como es muy sencillo...
Insertar archivo de imagen en MySQL
MySQL cuenta con el tipo BLOB (Binary Large Object) que puede albergar una gran cantidad de datos binarios. El tipo de datos BLOB es ideal para almacenar la información de la imagen. En MySQL, hay disponibles cuatro tipos de BLOB: TINYBLOB, BLOB, MEDIUMBLOB y LONGBLOB.
Para almacenar la información de la imagen, es necesario crear una tabla en la base de datos. El siguiente SQL crea la tabla images, la cual contiene un campo image que es del tipo LONGBLOB.
CREATE TABLE `images` ( `id` int(11) NOT NULL AUTO_INCREMENT, `image` longblob NOT NULL, `created` datetime NOT NULL, PRIMARY KEY (`id`) ) ENGINE=InnoDB DEFAULT CHARSET=utf8 COLLATE=utf8_unicode_ci;
Formulario de subida de la imagen
El siguiente HTML permitirá a los usuarios escoger el archivo de imagen que quieren subir.
<!DOCTYPE html> <html lang="en"> <body> <form action="upload.php" method="post" enctype="multipart/form-data"> Select image to upload: <input type="file" name="image"/> <input type="submit" name="submit" value="UPLOAD"/> </form> </body> </html>
Almacenar la imagen en la base de datos (upload.php)
El archivo upload.php contiene las siguientes funcionalidades:
- Comprueba si el usuario ha seleccionado un archivo de imagen para subirlo
- Recuperar el contenido del archivo de la imagen mediante el tmp_name
- Crear la conexión a la base de datos y seleccionarla
- Insertar el contenido binario de la imagen en la tabla images
- Mostrar el estado de la subida al usuario
<?php if(isset($_POST["submit"])){ $check = getimagesize($_FILES["image"]["tmp_name"]); if($check !== false){ $image = $_FILES['image']['tmp_name']; $imgContent = addslashes(file_get_contents($image)); /* * Insert image data into database */ //DB details $dbHost = 'localhost'; $dbUsername = 'root'; $dbPassword = '*****'; $dbName = 'programacionnet'; //Create connection and select DB $db = new mysqli($dbHost, $dbUsername, $dbPassword, $dbName); // Check connection if($db->connect_error){ die("Connection failed: " . $db->connect_error); } $dataTime = date("Y-m-d H:i:s"); //Insert image content into database $insert = $db->query("INSERT into images (image, created) VALUES ('$imgContent', '$dataTime')"); if($insert){ echo "File uploaded successfully."; }else{ echo "File upload failed, please try again."; } }else{ echo "Please select an image file to upload."; } } ?>
Recuperar la imagen de la base de datos (view.php)
En este archivo, vamos a recuperar el contenido de la imagen de la base de datos MySQL basándonos en el ID. Después, mostraremos la imagen en la página web. Para renderizar el archivo de imagen en la página web, utilizaremos el header Content-type.
<?php if(!empty($_GET['id'])){ //DB details $dbHost = 'localhost'; $dbUsername = 'root'; $dbPassword = '*****'; $dbName = 'programacionnet'; //Create connection and select DB $db = new mysqli($dbHost, $dbUsername, $dbPassword, $dbName); //Check connection if($db->connect_error){ die("Connection failed: " . $db->connect_error); } //Get image data from database $result = $db->query("SELECT image FROM images WHERE id = {$_GET['id']}"); if($result->num_rows > 0){ $imgData = $result->fetch_assoc(); //Render image header("Content-type: image/jpg"); echo $imgData['image']; }else{ echo 'Image not found...'; } } ?>