Sei sulla pagina 1di 6

IMAGENES Y

BASES DE DATOS
54 POWERUSR
.sql
UNA APLICACION PARA MANEJAR
IMAGENES CON PHP Y MYSQL

MARCELO RUIZ
NUESTRO GURU DEL DISEO WEB
marceloruiz@tectimes.com
ESTA ES LA FORMA EN QUE SE VEN LOS CAMPOS (YA CON ALGUNOS DATOS)
DESDE PHPMYADMIN. OBSERVEN QUE LOS CAMPOS BLOB NO MUESTRAN SU CONTENIDO,
PORQUE NO SE TRATA DE TEXTO. 01
FIGURA
LA APLICACION
En esta ocasin no desarrolla-
remos ningn ejemplo en
concreto, sino que veremos
cmo realizar esta tarea expli-
cando detenidamente cada
punto. Este sistema incluir
tres scripts principales:
I index.php: mostrar un lis-
tado con las imgenes guarda-
das en la base de datos.
I ver_imagen.php: se encarga-
r de leer la imagen de la base
de datos y de mostrarla en el
navegador.
I subir_imagen.php: presenta-
r un formulario para subir las
imgenes y guardarlas en la
base de datos.
Adems, vamos a utilizar una
base de datos db_archivos, con
una tabla tbl_archivos para
guardarlos. Para crear estos ob-
jetos podemos recurrir a cual-
quier cliente de MySQL que sea
capaz de conectarse con nues-
tra base de datos. Nuestro re-
comendado es MySQL-Front
(www.mysqlfront.de) o cualquiera de
los clientes de MySQL AB (la
empresa desarrolladora de la
base de datos), ya sea MyCC o
mysql (www.mysql.com). Si no po-
demos conectarnos en forma
remota con la base de datos,
deberemos utilizar php
MyAdmin; casi todos los ser-
vicios de hosting ya ofrecen
esta herramienta preinstalada.
Para crear la base de datos y
la tabla utilizaremos el si-
guiente cdigo SQL:
uchos se preguntarn: se puede guardar una imagen en
una base de datos? Y la respuesta es: por supuesto que s!
Un sistema de base de datos potente como MySQL permite
almacenar datos binarios como imgenes, documentos de Office, PDFs
o programas con la misma facilidad con la que guardamos texto.
Tradicionalmente, cuando se necesita utilizar una imagen en al-
guna aplicacin web, lo que se hace es subirla al servidor, copiar-
la en algn directorio determinado (que tenga permiso de escritu-
ra) y luego guardar el nombre de la imagen en la base de datos,
en un campo de texto comn y corriente (varchar, por ejemplo).
Nuestra propuesta es guardar el archivo mismo en la base de da-
tos para simplificar la aplicacin.
M
MUCHAS VECES, LOS DESARROLLADORES WEB SE VEN EN LA NECESIDAD DE SUBIR IMAGENES AL SERVIDOR, GUARDARLAS
Y MOSTRARLAS A LOS USUARIOS. EN ESTA NOTA EXPLICAREMOS UNA DE LAS TANTAS FORMAS QUE EXISTEN PARA
HACERLO, UTILIZANDO UNA BASE DE DATOS MYSQL PARA GUARDAR LAS IMAGENES SIN ACUDIR A ARCHIVOS INDIVIDUALES.
imagenes sql.qxd 9/12/03 15:22 Page 54
S
55 POWERUSR
CREATE database db_archivos;
USE db_archivos;
CREATE TABLE tbl_archivos (
IdArchivo int(11) NOT NULL auto_increment,
Nombre varchar(50) default NULL,
TipoMIME varchar(30) default NULL,
NombreMIME varchar(50) default NULL,
@ivo blob,
PRIMARY KEY (IdArchivo)
) TYPE=MyISAM;
Observen que nuestra tabla tbl_archivos
tiene un campo de tipo blob. La palabra
blob significa Binary Long OBject, y ser
aqu en donde guardaremos los datos bi-
narios de la imagen.
Vale aclarar que si bien este proyecto
ejemplifica el manejo de las imgenes,
puede adaptarse para cualquier tipo de ar-
chivos, como PDFs, programas y dems.
Tambin utilizaremos otro script secun-
dario, que ser nuestro archivo de cone-
xin. Este script contendr el cdigo ne-
cesario para comunicarse con la base de
datos. Llamamos a este script cnn.php y
su cdigo es el siguiente:
<?php /* cnn.php */
function cnn()
{
$host = "localhost";
$usuario = "marcelino";
$password = "notelodigo";
$bd = "db_archivos";
if (!($link=@mysql_pconnect($host, $usuario, $pass-
word))) die ("Error conectando a la base de datos.");
if (!@mysql_select_db($bd,$link)) die ("Error seleccio-
nando la base de datos.");
return $link;
}
$link = cnn ();
?>
GUARDAR LAS IMAGENES
Comenzaremos ahora a analizar el script
que se encargar de subir las imgenes al
servidor y de guardarlas en la base de da-
tos: subir_imagen.php.
El script en cuestin se muestra a conti-
nuacin:
<html>
<head>
<title>Subidor de im&aacute;genes</title>
<style>
body,td,p {
font-family: Verdana, Arial;
TRADICIONALMENTE, CUANDO SE NECESITA UTILIZAR UNA IMAGEN EN
ALGUNA APLICACION WEB, LO QUE SE HACE ES SUBIRLA AL SERVIDOR,
COPIARLA EN ALGUN DIRECTORIO DETERMINADO Y LUEGO GUARDAR EL
NOMBRE DE LA IMAGEN EN LA BASE DE DATOS, EN UN CAMPO DE TEXTO
COMUN Y CORRIENTE. NUESTRA PROPUESTA ES GUARDAR EL ARCHIVO
MISMO EN LA BASE DE DATOS PARA SIMPLIFICAR LA APLICACION.
font-size: 11px;
color: #666666;
}
</style>
</head>
<body bgcolor="white">
<?php
if (empty($_POST["Nombre"]) || empty($_FILES["Archivo"]))
{
?>
<form method="post" action="<?=$_SERVER["PHP_
SELF"]?>" enctype="multipart/form-data">
<h1>Subidor de im&aacute;genes</h1>
<h3>Utilice el siguiente formulario para subir
una imagen al servidor:</h3>
<table>
<tr>
<td><b>Nombre:</b></td>
<td><input type="text" name="Nombre" size=50></td>
</tr>
<tr>
<td><b>Archivo:</b></td>
<td><input name="Archivo" type="file"></td>
</tr>
<tr>
<td colspan="2" align="center"><input type
="submit"
value="Guardar"></td>
</tr>
</table>
<input type="hidden" name="MAX_FILE_SIZE"
value="100000">
</form>
<?php
}
else
{
$Nombre = $_POST["Nombre"];
$Archivo = $_FILES["Archivo"];
include ("cnn.php");
// Se subi un archivo?
if (!empty ($Archivo["name"]))
{
switch ($Archivo["type"])
{
case "image/gif";
$NombreMIME = "Imagen GIF";
break;
case "image/jpeg";
$NombreMIME = "Imagen JPEG";
break;
case "image/png";
$NombreMIME = "Imagen PNG";
break;
case "image/x-MS-bmp";
$NombreMIME = "Windows Bitmap";
ALGUNOS CLIENTES PARA MYSQL, COMO COCOAMYSQL, PARA MAC OS X
(N. DE LA R.: MARCE NO PUEDE CON SU GENIO...), INCORPORAN LA POSIBILIDAD
DE VISUALIZAR LOS CAMPOS BLOB COMO HEXADECIMAL O COMO IMAGENES. 02
FIGURA
*
imagenes sql.qxd 9/12/03 15:22 Page 55
56 POWERUSR
break;
default:
$NombreMIME = "Tipo de archivo desconocido";
}
// Abrimos el archivo subido
$fp = fopen($Archivo["tmp_name"], "r");
// Leemos el archivo subido
$ContenidoArchivo = fread($fp, filesize($Archivo["tmp_
name"]));
// Codificamos caracteres especiales
$ContenidoArchivo = AddSlashes($ContenidoArchivo);
}
else
{
$ContenidoArchivo = NULL;
echo "ADVERTENCIA: No se subio ningun archivo<br>";
}
$strSQL = "INSERT INTO tbl_archivos (Nombre, TipoMIME,
NombreMIME, Archivo)
VALUES ('$Nombre', '{$Archivo["type"]}', '$NombreMIME',
'$ContenidoArchivo')";
if ((@ mysql_query ($strSQL, $link))
&& @ mysql_affected_rows() == 1){
echo "<h1>Imagen guardada</h1>";
}
else
echo "<h1>No se pudo guardar
la imagen</h1>";
}
?>
<h3><a href="index.php">Haga clic
aqu&iacute;</a> para ver las im&aacute;
genes guardadas.</h3>
</body>
</html>
Este script est dividido en dos secciones.
La primera muestra si las variables de for-
mulario Nombre y Archivo estn vacas,
para lo cual utilizamos una funcin estn-
dar de PHP, empty. En este caso mostra-
mos un formulario en donde el usuario po-
dr colocar un nombre para el archivo, y
tambin tendr un control de tipo file, que
se ver en el navegador como una caja de
texto con un botn [Examinar] para bus-
car en el disco el archivo que va a subir.
Observen la presencia de un campo hidden
con el nombre MAX_FILE_SIZE. Este cam-
po nos permite establecer un lmite, en by-
tes, para los archivos que se van a subir.
Noten tambin la propiedad enctype-
="multipart/form- data" en la etiqueta
I $Archivo["name"]: nombre original
del archivo.
I $Archivo["type"]: tipo MIME del archivo.
I $Archivo["tmp_name"]: nombre del archivo tempo-
ral que se subi al servidor. Este archivo temporal no
tiene, necesariamente, el mismo nombre que el origi-
nal, y es eliminado del servidor una vez que pasa un
tiempo determinado.
I $Archivo["size"]: tamao del archivo, en bytes.
Seguimos con un control para saber si realmente se
subi un archivo. Luego, con una funcin switch eva-
luamos el tipo de archivo subido para darle un nom-
bre amigable. Por ejemplo, si el tipo de archivo es
image/jpeg, el nombre amigable que le daremos ser
Imagen JPEG. Guardamos este nombre en la variable
$NombreMIME, y ms tarde, lo guardaremos en el
campo NombreMIME de la base de datos.
Si eventualmente necesitamos trabajar con ms tipos
de archivos, deberemos tenerlos en cuenta en este
switch-case. De todas formas, observen que, si no se
conoce el tipo de archivo (caso default), se utiliza el
tipo MIME como nombre amigable.
Y ahora viene la parte que ms nos interesa: guardar
el archivo en la base de datos. En realidad, esto no es
ninguna ciencia, y es similar a guardar cualquier texto
en una base de datos, slo que en esta ocasin, el
texto o, mejor dicho, los datos binarios, estn dentro
del archivo y necesitamos leerlos primero.
Por esta razn, en primer lugar abrimos el archivo con
la funcin fopen. Esta funcin recibe dos argumentos: el
nombre del archivo que se quiere abrir y el modo de
apertura; en este caso "r" significa modo lectura, por
read, en ingls. La funcin devuelve un identificador
propio de ese archivo que guardamos en la variable $fp.
Para leer el archivo utilizamos la funcin fread. Esta
funcin necesita como argumentos el identificador
del archivo que se va a leer ($fp) y la cantidad de
03
FIGURA
AL PRESIONAR EL BOTON [EXAMINAR], EN EL SCRIPT SUBIR_IMAGEN.PHP,
SE ABRIRA UN CUADRO DE SELECCION DE ARCHIVOS, EN DONDE PODREMOS
ELEGIR LA IMAGEN QUE QUEREMOS SUBIR.
OBSERVEN QUE NUESTRA
TABLA TBL_ARCHIVOS
TIENE UN CAMPO DE TIPO
BLOB. LA PALABRA BLOB
SIGNIFICA BINARY LONG
OBJECT, Y SERA AQUI
EN DONDE GUARDAREMOS
LOS DATOS BINARIOS DE
LA IMAGEN. VALE ACLARAR
QUE SI BIEN ESTE
PROYECTO EJEMPLIFICA EL
MANEJO DE LAS IMAGENES,
PUEDE ADAPTARSE PARA
CUALQUIER TIPO
DE ARCHIVOS, COMO PDFS,
PROGRAMAS Y DEMAS.
<form>. Esta propiedad es
siempre necesaria cuando se
envan archivos al servidor.
La segunda parte del script co-
mienza con el else de la condi-
cin que controlaba que las va-
riables de formulario Nombre y
Archivo no estuvieran vacas.
Comenzamos pasando los va-
lores de esas variables a varia-
bles con nombres ms senci-
llos, para facilitar el trabajo.
Noten que el campo Archivo
se obtiene mediante el vector
$_FILES, en lugar de $_POST,
por ser un archivo.
La variable $Archivo es, en
realidad, un vector que nos
proporciona mucha informacin
sobre el archivo que se subi:
imagenes sql.qxd 9/12/03 15:22 Page 56
57 POWERUSR
Existe una buena cantidad de hostings accesibles
que nos sern de gran utilidad para alojar este
y otros proyectos que queramos realizar.
En la tabla mostramos algunos de los planes ms
econmicos que pudimos encontrar.
En todos los casos se incluyen PHP, MySQL, soporte
para mltiples cuentas POP3, acceso por FTP
y todas las caractersticas de un servicio profesional.
Aqu hay que tener en cuenta varios factores, no slo el
precio y la transferencia, que son las variantes. Muchos
hostings ofrecen transferencias altas o ilimitadas,
aunque esto puede volverse en nuestra contra. Por
qu? Simplemente, porque estas empresas suelen
alojar una gran cantidad de sitios web en el mismo
servidor, lo que afecta la velocidad de conexin.
Por eso, muchas veces pueden ofrecernos una
transferencia muy elevada, pero si la velocidad no es
buena, nunca podremos ni siquiera aprovecharla.
Por todos estos motivos, siempre es recomendable
conocer algn sitio en el hosting que nos interese.
HOSTING PAGO
Recientes hallazgos de nuestro equipo arqueolgico in-
dican que todava quedan algunos servicios de hosting
gratuito para PHP y MySQL.
PHP Freaks ofrece uno de los mejores, a cambio de
links de texto al pie de todas nuestras pginas.
El servicio es muy bueno, ya que brinda 100 MB de es-
pacio, 1 GB de transferencia mensual, interfaz de con-
trol Cpanel (www.cpanel.net), la ltima versin de PHP y
servidores Apache 1.3.28, FTP y MySQL. Slo nos pide
que cumplamos con algunos requisitos, sin los cuales
nuestro sitio ser dado de baja en forma inmediata. Por
ejemplo, entre varias clusulas que deberemos aceptar,
es indispensable tener un dominio propio, dar de alta
nuestro sitio en Open Directory Project (dmoz.org) y co-
menzar a subir el contenido en un tiempo que no supe-
re los 5 das desde que contratamos el servicio.
Quienes posean dominios .ar debern tener en cuenta que
los cambios de DNS y, peor an, el registro de nuevos do-
minios, suelen demorar ms tiempo, por lo que aconseja-
mos tener el dominio registrado y apuntando a los DNSs
de PHP Freaks antes de darse de alta en el servicio.
HOSTING GRATUITO
SI QUEREMOS ALOJAR UNA APLICACION COMO LA QUE VIMOS EN ESTA NOTA, NECESITAREMOS CONTRATAR UN SERVICIO
DE HOSTING QUE NOS PROVEA, ADEMAS, DE SOPORTE PARA PHP Y MYSQL. BASICAMENTE, TENEMOS DOS OPCIONES:
PAGAR O UTILIZAR UN SERVICIO GRATUITO, CON LAS LIMITACIONES QUE ESTO IMPLICA. VEAMOS AMBOS CASOS:
EMPRESA PLAN ESPACIO TRANSFERENCIA PRECIO ARGENTINA (PESOS) PRECIO INTERNACIONAL (DOLARES) URL
Dattatec Empresa 50 MB 8 GB $ 2,50 U$S 0,90 www.dattatec.com
XMundo 50MB 50 MB 2 GB $ 5 U$S 1,75 www.xmundo.net
123tuweb Host 40 40 MB Ilimitado $ 5 U$S 2,49 www.123tuweb.com
PARA CREAR OBJETOS CON LOS QUE TRABAJAREMOS, PODEMOS RECURRIR A CUALQUIER CLIENTE
DE MYSQL QUE SEA CAPAZ DE CONECTARSE CON NUESTRA BASE DE DATOS. NUESTRO RECOMENDADO
ES MYSQL-FRONT (www.mysqlfront.de) O CUALQUIERA DE LOS CLIENTES DE MYSQL AB
(LA EMPRESA DESARROLLADORA DE LA BASE DE DATOS), YA SEA MYCC O MYSQL (www.mysql.com).
*
imagenes sql.qxd 9/12/03 15:22 Page 57
58 POWERUSR
bytes que queremos leer. En nuestro caso, obtenemos esa canti-
dad utilizando la funcin filesize, aunque tambin podramos
hacerlo con $Archivo["size"].
Un aspecto que debemos tener en cuenta es que no podremos in-
sertar caracteres no admitidos por MySQL. Por ejemplo, si quere-
mos poner una comilla simple ('), MySQL lo entender como el
final de una cadena de texto, con lo cual nos dar error; por lo
tanto, debemos reemplazarla por \'. Podemos hacer todos estos
cambios de una sola vez por medio de la funcin AddSlashes.
Finalmente, llega el momento de insertar la nueva imagen, con to-
dos sus datos, en la base MySQL. Como vern, la instruccin SQL no
encierra demasiados secretos. Observen que el contenido del archivo
se inserta directamente como si se tratara de cualquier otro texto.
MOSTRAR LAS IMAGENES
Bien, ya tenemos nuestra base de datos con las imgenes guarda-
das en su interior, con algunos datos adicionales como el nom-
bre, el tipo MIME y el nombre del tipo de archivo. Ahora vamos
a crear una pgina sencilla, que se encargar de mostrar las im-
genes (index.php) en una tabla HTML.
Este script es muy simple: consiste en ha-
cer una consulta a la base de datos y reco-
rrer los resultados utilizando una tabla:
<html>
<head>
<title>Im&aacute;genes</title>
<style>
body,td,p {
font-family: Verdana, Arial;
font-size: 11px;
color: #666666;
}
</style>
</head>
<body bgcolor="white">
<h1>Im&aacute;genes</h1>
<?php
include ("cnn.php");
$strSQL = "SELECT * FROM tbl_archivos";
$result = mysql_query ($strSQL);
if (mysql_num_rows ($result)){
?>
<table cellpadding="4" cellspacing="0"
border="1">
<tr><td>Imagen</td><td>Tipo de
archivo</td><td>Foto</td></tr>
<?php
while ($rsArchivos = mysql_fetch_array
($result)){
?>
<tr>
<td><?=$rsArchivos["Nombre"]?>
</td>
<td><?=$rsArchivos["NombreMIME"]?>
</td>
<td><img src="ver_imagen.php?
IdArchivo=<?=$rsArchivos["
IdArchivo"]?>"></td>
</tr>
<?php
}
}
else
echo "<h3>No hay im&aacute;genes
para mostrar</h3>";
?>
</body>
</html>
Como ven, lo nico extrao que encontra-
mos ac es la forma en que se muestra la
imagen. Normalmente, para esta tarea se
utiliza la etiqueta <img> con la propiedad
src y la ruta de la imagen, por ejemplo:
04
FIGURA
LA PAGINA PRINCIPAL DE NUESTRA APLICACION MOSTRARA
TODAS LAS IMAGENES QUE HAY EN LA BASE DE DATOS,
PARA LO CUAL UTILIZA EL SCRIPT VER_IMAGEN.PHP.
SI LOS ARCHIVOS QUE QUEREMOS SUBIR SON MUY PESADOS,
PROBABLEMENTE EL SCRIPT NOS DE UN ERROR DE TIME OUT. ESTO SE DEBE
A QUE TODOS LOS SCRIPTS TIENEN ASIGNADO UN TIEMPO MAXIMO DURANTE
EL CUAL PUEDEN EJECUTARSE, Y SI LO EXCEDEMOS MIENTRAS SUBIMOS
EL ARCHIVO, EL SERVIDOR FINALIZARA ABRUPTAMENTE SU EJECUCION.
*
imagenes sql.qxd 9/12/03 15:22 Page 58
59 POWERUSR
<img src="imagenes/gatita.jpg">
Pero si prestan atencin, vern que en
nuestro script el valor de la propiedad src
es un script PHP:
<img src="ver_imagen.php?IdArchivo=
<?=$rsArchivos["IdArchivo"]?>">
Al ser procesado por el intrprete de PHP,
por ejemplo para la imagen cuyo IdArchi-
vo es 4, quedara de la siguiente manera:
<img src="ver_imagen.php?IdArchivo=4">
De esta forma, haremos que el script
ver_imagen.php realice una consulta a la
base de datos, obtenga el contenido del
archivo solicitado y lo muestre en el nave-
gador como una imagen.
ENVIAR LA IMAGEN
AL NAVEGADOR
Este ser el script ms simple y breve,
pero tambin el ms importante. Su mi-
sin ser realizar una consulta a la base
de datos y traer los campos Archivo y
TipoMIME de la tabla tbl_archivos, de
acuerdo con el IdArchivo pasado a tra-
vs de la URL.
Si antes se preguntaron para qu guard-
bamos el tipo MIME, ahora lo entendern.
Necesitamos enviar una cabecera Content-
Type al navegador para indicarle qu tipo
de contenido le estamos mandando, de
modo que sepa cmo manipularlo:
<?php
include ("cnn.php");
$IdArchivo = $_GET["IdArchivo"];
$strSQL = "SELECT Archivo, TipoMIME FROM tbl_archivos
WHERE IdArchivo=$IdArchivo";
$result = mysql_query ($strSQL);
if (mysql_num_rows ($result)){
$datos = mysql_fetch_array ($result);
header ("Content-Type: {$datos["TipoMIME"]}");
echo $datos["Archivo"];
}
?>
Al llamar a este archivo, por ms que su
extensin sea .php, el navegador entende-
r que lo que est recibiendo es una ima-
gen, gracias a la cabecera Content-Type,
y entonces la mostrar correctamente.
Si hacemos clic derecho sobre la imagen
para guardarla en nuestro disco, sta lo
har como ver_imagen.php. Para evitarlo,
podemos enviar una cabecera adicional
con el nombre de la imagen:
header ("Content-Disposition: filename={$datos["Archivo"]}");
MULTIPLES USOS
Como ya se habrn dado cuenta, este
ejemplo para guardar imgenes en una
base de datos puede utilizarse para infi-
nidad de aplicaciones, incluso para cual-
quier tipo de archivos. La nica limita-
cin que debemos considerar es el peso
de los archivos.
Si los archivos que queremos subir son
muy pesados, probablemente el script
nos d un error de time out.
Esto se debe a que todos los scripts
tienen asignado un tiempo mximo du-
rante el cual pueden ejecutarse, y si lo
excedemos mientras subimos el archivo,
el servidor finalizar abruptamente su
ejecucin. Podemos aumentar este tiempo
mediante la funcin set_time_limit (es
probable que en muchos hostings com-
partidos el uso de esta funcin no est
habilitado). Por ejemplo, para asegurarnos
un tiempo mximo de ejecucin de 200
segundos, usamos set_time_limit (200).
De esta manera, finalmente tendrn un
sistema para manejar archivos muy efi-
ciente y fcil de adaptar a cualquier tipo
de aplicaciones I
Hagan clic en
laquiero.tectimes.com
y van a poder comprar las
USERS que quieran, o
suscribirse.
Dense el gusto de
estar al da con las ltimas
>> users.tectimes.com
Y AHORA VIENE LA PARTE QUE MAS
NOS INTERESA: GUARDAR EL ARCHIVO
EN LA BASE DE DATOS. EN REALIDAD,
ESTO NO ES NINGUNA CIENCIA,
Y ES SIMILAR A GUARDAR CUALQUIER
TEXTO EN UNA BASE DE DATOS,
SOLO QUE EN ESTA OCASION,
EL TEXTO O, MEJOR DICHO, LOS DATOS
BINARIOS, ESTAN DENTRO DEL ARCHIVO
Y NECESITAMOS LEERLOS PRIMERO.
imagenes sql.qxd 9/12/03 15:22 Page 59

Potrebbero piacerti anche