Maestros del Web


Estás en Inicio / Editorial / Desarrollo Web

29.03.2007

Revisar las imágenes antes de subirlas

Cuando se quiere que una imagen seleccionada en un formulario pueda ser previsualizada antes del envío del mismo, y poder controlar cosas como tipo, tamaño o dimensiones; podemos encontrarnos con serios problemas. Con este tutorial acompañado de un sencillo ejemplo, podemos ver como conseguirlo.

Limpiando un campo file

Comprobar que un fichero tenga una extensión determinada no es muy difícil con javascript, pero cuando lo tenemos seleccionado y no es correcto, podemos cometer el error de pulsar sobre el botón de envío.

Debido a ello vamos a proponer un script que permita previsualizar la imagen que seleccionemos, y en el caso de que el fichero seleccionado no tenga la extensión de imagen que nos interese, limpiar el campo file.

La estructura será así:

function checkear_extension(fichero)	{
	// definimos antes los métodos prever() y limpiar()
	(/.(gif|jpg|png)$/i.test(fichero.value)) ? prever() : limpiar();
}

La función limpiar():

function limpiar()	{
	f = document.getElementById("archivo");
	nuevoFile = document.createElement("input");
	nuevoFile.id = f.id;
	nuevoFile.type = "file";
	nuevoFile.name = "archivo";
	nuevoFile.value = "";
	nuevoFile.onchange = f.onchange;
	nodoPadre = f.parentNode;
	nodoSiguiente = f.nextSibling;
	nodoPadre.removeChild(f);
	(nodoSiguiente == null) ? nodoPadre.appendChild(nuevoFile):
		nodoPadre.insertBefore(nuevoFile, nodoSiguiente);
}

Como puede verse la forma de limpiar un campo file es algo rebuscada, pero después de hacer muchas pruebas, es la única manera funcional en los tres navegadores probados. De todos modos, simplemente se podría comprobar la extensión durante la validación del formulario:

-onsubmit=''return/.(gif|jpg|png)$/i.test(archivo.value)"

La visualización

Mostrar una imagen seleccionada desde un campo file podría parecernos cosa fácil, pero por razones de seguridad no se pueden mostrar las imágenes a no ser que estén en la red (tal vez puedan encontrarse truquillos que funcionen en algún navegador, pero no sirven en todos).

Solo queda mostrar el método prever que definiremos dentro del método checkear_extension(), que definitivamente se quedaría de la siguiente manera:

function checkear_extension(fichero)	{

	function prever() {
		var campos = new Array("maxpeso", "maxalto", "maxancho");
		for (i = 0, total = campos.length; i < total; i ++)
			fichero.form[campos[i]].disabled = false;
		actionActual = fichero.form.action;
		targetActual = fichero.form.target;
		fichero.form.action = “previsor.php”;
		fichero.form.target = “ver”;
		fichero.form.submit();
		for (i = 0, total = campos.length; i < total; i ++)
			fichero.form[campos[i]].disabled = true;
		fichero.form.action = actionActual;
		fichero.form.target = targetActual;
	}

	function no_prever() {
		alert(”El fichero seleccionado no es válido…”);
		limpiar();
	}

	(/.(gif|jpg|png)$/i.test(fichero.value)) ? prever() : no_prever();
}

Como comentarios adicionales, solo quedaría matizar que la visualización no es otra cosa que el envío del formulario con la habilitación de los campos que servirán de control, hacia una ventana, que en este caso concreto es un iframe del mismo documento.

El resto de javascript

Lo que quedaría por definir es un sistema validador para evitar el envío del formulario en el caso de no haber seleccionado una imagen válida, y un método que reciba los valores sobre la imagen que se seleccione.

Para la primera definición supondremos que la etiqueta form tiene algo de esto: <form onsubmit="return validar(this)">

function validar(f)	{
	enviar = /.(gif|jpg|png)$/i.test(f.archivo.value);
	if (!enviar)	alert("seleccione imagen");
	return enviar;
}

Y los datos de la previsualización los recibirá un método que llamaremos datosImagen(), cuyos argumentos serán, el peso, anchura, altura y nº de error (si el error es “0″ significa sin error).

function datosImagen(peso, ancho, alto, error)	{
	function mostrar_error()	{
		enviar = false;
		mensaje = "Ha habido un error (error nº " + error + "):";
		if (error % 2 == 1) // tipo incorrecto
			mensaje += "nel fichero no es válido";
		error = parseInt(error / 2);
		if (error % 2 == 1) // excede en peso
			mensaje += "nla imagen pesa mogollón (" + peso + ").";
		error = parseInt(error / 2);
		if (error % 2 == 1) // excede en anchura
			mensaje += "nla imagen excede en anchura (" + ancho + ").";
		error = parseInt(error / 2);
		if (error % 2 == 1) // excede en altura
			mensaje += "nla imagen excede en altura (" + alto + ").";
		error = parseInt(error / 2);
		alert (mensaje);
		with (document.forms)	{
			formu.peso.value = 0;
			formu.ancho.value = 0;
			formu.alto.value = 0;
		}
		limpiar();
	}

	if (error == 0)	with (document.forms)	{
		formu.peso.value = peso;
		formu.ancho.value = ancho;
		formu.alto.value = alto;
	}
	else	mostrar_error();
}

Sobre la forma de codificar los errores no voy a hacer comentarios para que este artículo no se haga demasiado extenso.

Gestión desde el servidor

La página destino del formulario durante este sistema de previsualización, debe ser una página web, con una imagen (que en este caso será el fondo de la página), y el contenido de esa imagen será el recibido por la imagen del formulario.

<?php
	session_start();
	$defecto = "webmaster.gif";
	$Ok = isset($_FILES["archivo"]);
	$url = ($Ok) ? $_FILES["archivo"]["tmp_name"] : $defecto;
	list($anchura, $altura, $tipoImagen, $atributos) = getimagesize($url);
	$error = (isset($atributos)) ? 0 : 1;
	$los_tipos = array(”gif”, “jpg”, “png”);
	$tipo = ($Ok) ? “image/”.$los_tipos[$tipoImagen - 1] : “image/gif”;
	$fichero = ($Ok && ($error == 0)) ? $_FILES["archivo"]["name"] : $defecto;
	$tam = filesize($url);
	$OkTam = isset($_POST["maxpeso"]);
	$OkAncho = isset($_POST["maxancho"]);
	$OkAlto = isset($_POST["maxalto"]);
	$maxTam = ($OkTam) ? (int) $_POST["maxpeso"]: 100000;
	$maxAncho = ($OkAncho) ? (int) $_POST["maxancho"]: 640;
	$maxAlto = ($OkAlto) ? (int) $_POST["maxalto"]: 480;
	$error += ($tam <= $maxTam) ? 0 : 2;
	$ancho = ($error == 1) ? 0 : $anchura;
	$alto = ($error == 1) ? 0 : $altura;
	$error += ($ancho <= $maxAncho) ? 0 : 4;
	$error += ($alto <= $maxAlto) ? 0 : 8;
	$datos = ($error == 0) ? $url : $defecto;
	$onload = ($Ok) ? “onload=’parent.datosImagen($tam, $ancho, $alto, $error)’”: ”;
	$datos_imagen = fread(fopen($datos, “rb”), filesize($datos));
	$_SESSION["cont"] = $datos_imagen;
	$_SESSION["tipo"] = ($error == 0) ? $tipo : “image/gif”;
?>
<html>
<head>
<style type=”text/css” >
html	{
	margin: 0;
	height: 100%;
}
body	{
	height: 100%;
	background-image: url(previendo.php?dato=<?=$fichero;?>);
	background-repeat: no-repeat;
	background-position: center center;
}
</style>
</head>
<body <?=$onload;?>>

</body>
</html>

Resumiendo el código expuesto, diremos que se crea una sesión php y se guarda el código de la imagen y su tipo; además se pone como fondo de la página un fichero (previendo.php) que a pesar de tener parámetro, en la página no se consideran, la razón de esta “curiosidad” es evitar que la imagen sea mostrada por los navegadores desde la memoria caché.

Otra curiosidad es la definición en la etiqueta body (sus estilos se ven en la sección style de la cabecera del documento) del evento load (onload), donde se envían datos a la ventana “parent”, con información de la imagen y un código de error, que de ser distinto de 0 en la página “padre” mostrará una alerta con la descripción del mismo.

Para finalizar mostraremos el contenido del fichero previendo.php, que como se puede adivinar, tan solo envía el contenido de la imagen a la consola:

<?php
session_start();
$url = ($_SESSION["cont"] == “”)
	? fread(fopen(”webmaster.gif”, “rb”), filesize(”webmaster.gif”))
	: $_SESSION["cont"];
$tip = ($_SESSION["tipo"] == “”)
	? “image/gif”
	: $_SESSION["tipo"];
header(”Content-type: $tip”);
echo $url;
session_destroy();
?>

Solo nos queda mostrar este código en funcionamiento; para ello podemos visualizar el formulario ejemplo.

Califica esta nota:

1 estrella2 estrellas3 estrellas4 estrellas5 estrellas (11 votos, promedio: 3.91 de 5)
Loading ... Loading ...

Sobre el autor

Pepe Molina
Se desarrolla como webmaster de caricatos.net, autor de varios artículos y manuales sobre diseño y desarrollo web.

Si eres nuevo en Maestros del Web y te agradan nuestras publicaciones, te invitamos a suscribirte a nuestro Feed.

Sindícanos en: Google Reader, Bloglines, My Yahoo o My MSN | ¿Qué es el Feed?

Comentarios

13 comentarios en total.

  1. TBS 11.10.2007 - 12:15 - #

    Podrias dejar un poco mas explicito este ejemplito amigo mio, es ke no se donde poner las cosas…

  2. AAD 18.10.2007 - 05:27 - #

    La verdad, es que un poquito mas explicado iria mejor, porque lo estoy probando y no lo entiendo mucho…

    Muchas gracias.

  3. Angel_Dark_Cherry 24.10.2007 - 12:42 - #

    Podrias hacernos el favor de incluir los archivos de ejemplo…

  4. Camilo 28.10.2007 - 03:39 - #

    Sin los archivos de ejemplo es complicado.

  5. Solange 30.01.2008 - 06:17 - #

    Gracias por la nota, tengo algunas dudas pero a medida que lo valla haciendo seguro que se van a ir resolviendo, los archivos de ejemplo cuales son ?

  6. antonio 31.01.2008 - 06:02 - #

    No consigo hacerlo funcionar en mi proyecto. Te ruego por favor me lo envies a mi email me urge, te lo agradecería muchísimo. Gracias

  7. Anonymous 11.02.2008 - 15:43 - #

    pucha, muy tranca tu explicacion bueno aunque domino dom no me sale muy bien que digamos si puedes profundizar seria excelente

  8. luis samuel 19.03.2008 - 08:57 - #

    Es un fume pero logre entenderlo…
    Venezuela si puede!!!!!!
    Programadores al poder :D

  9. caricatos 24.03.2008 - 16:31 - #

    Para quienes quieren el código fuente, se puede descargar desde: http://www.caricatos.net/articulos/check_form.zip

    Saludos ;-)

  10. Ness 09.05.2008 - 09:34 - #

    Gracias por este codigo amigo, me sirvio de ejemplo para poder programar un sistema de noticias, donde ahora puedo ver la foto que voy a subir, antes de subirla, Tu codigo tiene algunos errorsitos en el JavaScript, pero quizás es porque esos errores se me generan a mi al trabajar con PHP. Aun estoy depurando el código, pero son problemas menores que no importan y no afectan el desempeño del sistema. El usuario ni cuenta se da que la ventana le esta marcando un warning en JAVASCRIPT porque no encuentra un objeto. Pero eso no afecta en nada el funcionamiento del mismo.

  11. majo 29.05.2008 - 13:02 - #

    Hay algún ejemplo similar pero para asp.

  12. Shalom 06.06.2008 - 09:48 - #

    Y que pasaría si subo un archivo cualquiera, por ejemplo un Shell de PHP, esto me serviría para sañar tu servidor, ya arriba el archivo.jpg que me da acceso a tu server entro, lo renombro con archivo.php, Entonces engaño a tu validación pues solo checas extenciones no contenido del archivo.

  13. aldo 12.06.2008 - 13:22 - #

    buenas caricatos, exelente ejemplo que me sirvio para gstion de galeria de imagenes.

    salu2

Deja tu Comentario


Maestros del Web se reserva el derecho de moderación de los comentarios. Evita utilizar palabras soeces, ataques directos, descalificativos, insultos, de lo contrario tu comentario será eliminado.


Boletín

Agrega nuestro feed a  Netvibes
wikio Add to Technorati Favorites

-


Maestros del Web es el punto de encuentro para los entusiastas de la red.

Creative Commons by-nc-sa 3.0 | Política de Privacidad | CMS: Wordpress