Un espacio para los entusiastas del web

Revisar las imágenes antes de subirlas

Publicado el 29 de Marzo, 2007

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.

Otros artículos relacionados

Califica esta nota:

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

Comentarios

  1. TBS

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


  2. AAD

    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

    Podrias hacernos el favor de incluir los archivos de ejemplo…


  4. Camilo

    Sin los archivos de ejemplo es complicado.


  5. 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

    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

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


  8. luis samuel

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


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

    Saludos ;-)


  10. 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

    Hay algún ejemplo similar pero para asp.


  12. Shalom

    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. buenas caricatos, exelente ejemplo que me sirvio para gstion de galeria de imagenes.

    salu2


  14. Hola:

    Shalom: Simplemente usando getimagesize (creo que no te has fijado bien) se puede controlar las “malas ideas” de muchos como pareces tener tú.

    Saludos ;-)


  15. muy bien caricatos pero como hago luego para guardar la imagen en un archivo especifico por ejmplo imagenes en mi sitio web.


  16. Francisco Jose

    Gracias por este manual, que he conseguido implantar en el panel de control de mi web y funciona de maravilla. Es estupendo y no he encontrado nada que se le parezca en infalibilidad en cualquier browser.

    Te escribo porque, como en el proceso de visualización de la imagen, ésta ya se visualiza desde el servidor, me ayudarías mucho si me dijeras si es posible trabajar con lo que ya está subido para guardar la imagen en una carpeta concreta. Yo, por ahora, lo que hago es subirla como si de un formulario con campo file normal se tratara, con lo cual creo que la subo dos veces.

    No soy un experto en php y no he conseguido interpretar bien tu script “receptor.php”, que intuyo que es donde debe estar la “respuesta a mi duda”.

    Gracias


  17. miriam

    Aquí encontré un ejemplo de esto que has explicado y se puede ver como funciona en directo para después descargar.
    http://www.rincondelcodigo.com/ver.php?var=167&num=79


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.


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.

Más artículos de Pepe Molina

Las Notas en tu correo


Acerca de

Maestros del Web nace cuando intentamos traducir Webmaster al Español. Nacimos orientados al diseño y desarrollo web. Hoy somos un espacio de apoyo para los entusiastas que participan en proyectos en la red.
Leer más de Maestros del Web