Checkeo de 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 forma que funciona 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 definiremeos 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 esta guisa:
<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 hemos creado el formulario que se puede ver en el siguiente enlace: formulario de ejemplo.

Enlaces interesantes sobre el tema

Este tema es muy recurrente en los Foros del web:



Comentarios

Nombre: Isabel
Procedencia: Colombia
Fecha de envío: 30 de marzo de 2013, a las 06:16.
Valoración:
comentario:

Caricatos, buenas tardes

El script para validar la carga de imagenes es excelente, tengo solo una duda. Cuando estoy cargando una imagen no se activa el gift del reloj de espera.

En este elace no funciona http://www.caricatos.net/articulos/check_form.html en este otro si funciona
http://www.caricatos.net/articulos/check_form.php, pero no logro saber por que, me colaboras por favor

Graias

Isabel


Nombre: Juliana Gonzalez
Procedencia: Mexicana
Fecha de envío: 3 de agosto de 2011, a las 19:47.
Valoración:
comentario:

Buen dia el ejemplo me es de gran utilidad para mi pagina, lo que necesito saber es por que al descargar el codigo no funciona de manera correcta, si puedo previsualizar la imagen pero no me muestra ni su tamaño ni ancho ni alto ni nada, no se cual sea el problema, ojala y me puedas ayudar gracias.


Nombre: zerokilled
Procedencia: Estados Unidos
Fecha de envío: 30 de diciembre de 2010, a las 03:31.
comentario:

¡que tal, pepe!

desde hace tiempo había sabido de este artículo pero no me habia animado a leerlo hasta hoy que lo repase debido a varios temas formulados en forosdelweb. solo quería comentarte (aunque quizas ya lo conoces) que hay varias lineas de la función limpiar que se pueden reducir utilizando el método replaceChild. así te evitas tener que obtener el próximo nodo del elemento para luego invocar insertBefore.

[code]
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;

f.parentNode.replaceChild(nuevoFile, f);
/* nodoPadre = f.parentNode;
nodoSiguiente = f.nextSibling;
nodoPadre.removeChild(f);
(nodoSiguiente == null) ? nodoPadre.appendChild(nuevoFile):
nodoPadre.insertBefore(nuevoFile, nodoSiguiente);
*/
}
[/code]

saludos! =D


Nombre: Juan Pablo Sora
Procedencia: Bogotá Colombia
E-Mail: pepejp007@hotmail.com
Fecha de envío: 31 de agosto de 2010, a las 04:14.
comentario:

Felicitaciones un script bien mezclado php, javascript y html, cumple con lo importante: carga la imagen teniendo en cuenta las características de la misma. De nuevo gracias!!


Nombre: Jorge Sánchez
Procedencia: Zaragoza
E-Mail: brunosanchez82@hotmail.com
Fecha de envío: 10 de diciembre de 2009, a las 18:12.
comentario:

Buenas tardes amigo excelente script para mostrar las imagenes gracias por compartir, tengo la siguiente duda necesito enviar las imagenes a un documento pdf creado en tcpdf quisiera saber que variable se le asigna a la imagen para poder realizar lo mencionado anteriormente si es posible


Nombre: Jorge Sánchez
Procedencia: Zaragoza
E-Mail: brunosanchez82@hotmail.com
Fecha de envío: 10 de diciembre de 2009, a las 18:11.
comentario:

Buenas tardes amigo excelente script para mostrar las imagenes gracias por compartir, tengo la siguiente duda necesito enviar las imagenes a un documento pdf creado en tcpdf quisiera saber que variable se le asigna a la imagen para poder realizar lo mencionado anteriormente si es posible


Nombre: casimira
Fecha de envío: 5 de noviembre de 2009, a las 22:56.
comentario:

Hola caricatos, me intereso mucho el codigo que presentas solo que cuando lo quiero probar con el navegador explorer no me funciona, a menos que sea la version 8 y necesito que funcione en cualquier version.Me gustaria saber a que se debe, porq ni siquiera el codigo fuente que pones para descargar me funciona en el explorer y lo raro es que en el mozilla si lo hace. Te agradeceria si me resulves mi duda.
Saludos


Nombre: Alfredo
Procedencia: México
E-Mail: auditoriawireless@hotmail.com
Fecha de envío: 28 de mayo de 2009, a las 01:29.
comentario:

QUE TAL MUY INTERESANTE TU CÓDIGO, PODRIAS COMENTARLO UN POCO MAS. DESEO PASARLO A JSP Y REALMENTE ME CUESTA TRABAJO. GRACIAS Y SALUDOS!!!


Fecha de envío: 28 de enero de 2009, a las 20:53.
comentario:

Estaria bien algo asi en Asp


Nombre: Salbatore
Fecha de envío: 9 de diciembre de 2008, a las 19:26.
comentario:

Hola,

Buscando por google me encontre con esto... bufffff... que bueno!.

Muchisimas gracias por el tutorial!.

Ahora me toca mordisquearlo durante mucho mucho tiempo... jeje.

Gracias!.


Nombre: Francisco José Segura
Procedencia: España - Alicante
E-Mail: fsnoya@gmail.com
Fecha de envío: 10 de octubre de 2008, a las 12:10.
comentario:

Hola Caricatos,
Ya hace tiempo que uso estos scripts pues no fallan en ningún navegador de los que he probado: gracias.
Te hago un pedido, que no estoy seguro si es posible o ni siquiera si es correcto.
Vamos allá: por lo que entiendo de tu propuesta, la imagen visualizada ya se encuentra en el servidor. Yo, lo que hago es someter el formulario como si de un campo file normal se tratara (para subir la imagen al servidor), por lo que concluyo (a lo mejor equivocadamente) que envío la imagen dos veces: una para visualizar y otra para guardar.
Mi pregunta: ¿no podrías enseñarnos un script para aprovecha los datos que ya están en el servidor y guardar la imagen sin subirla de nuevo? Sé que hay uno que le llamas "receptor.php" con el que a lo mejor se pueda hacer, pero no he conseguido interpretarlo para hacer esto que te pido.
Ya me dirás: un abrazo. Paco


Nombre: Caricatos
Procedencia: España
URL: http://www.caricatos.net
Fecha de envío: 15 de marzo de 2008, a las 07:28.
comentario:

Hola:

Se pueden encontrar los archivos originales en la siguiente dirección: [Subrayado] http://www.caricatos.net/articulos/check_form.zip[Subrayado]


Nombre: Javier
Procedencia: Nicaragua
E-Mail: jehernandez81@gmail.com
Fecha de envío: 7 de febrero de 2008, a las 23:33.
comentario:

UN RECOMENDACION.

ME GUSTARIA SABER SI PUEDES COLOCAR EL SOURCE(CODIGO FUENTE) EN UN ZIP PARA QUE PODAMOS PROBAR EL CODIGO POR QUE LOS TROSOS DE CODIGO QUE PONES A MI PARECE YO LOS HE PROBADO TANTAS Y NO ME FUNCIONAN TALVES PUEDAS SUBIR CODIGO PARA QUE PODAMOS OBSERVARLO Y PROBARLO.

ATTE. JAVSOFT


Colabore enviando su comentario

Nombre
Procedencia
Página web
E-mail *
Evaluación evaluarevaluarevaluarevaluarevaluarevaluarevaluarevaluarevaluarevaluar
Código de envío

Rellene este campo con la clave de la imagen: codigo de envío

Nota Importante

El campo E-Mail es obligatorio para activar por correo electrónico el comentario (si no desea que se haga público, marque la casilla "anonimato"). También es obligatorio el código "captcha" (el número que se ve en la imagen adjunta); y por supuesto, debe existir un comentario.

Puede encontrar información sobre este sistema de comentarios en este enlace: Ponga comentarios en su web.

Edición negrita cursiva subrayado   alineación izquierda alineación derecha alineación centrada alineación justificada   Insertar enlace insertar imagen   Emoticones: [:)] [:(] [:x] [BIEN] [MAL] [SI] [NO] [APLAUSOS] [MEJORABLE] [¡A VER!] [¡DÉJAME PENSAR!] [FLIPE] [¡SIN PALABRAS!]
Copyright © 2006-2018 www.caricatos.net
Visitas: 26429