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.
Podrias dejar un poco mas explicito este ejemplito amigo mio, es ke no se donde poner las cosas…
La verdad, es que un poquito mas explicado iria mejor, porque lo estoy probando y no lo entiendo mucho…
Muchas gracias.
Podrias hacernos el favor de incluir los archivos de ejemplo…
Sin los archivos de ejemplo es complicado.
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 ?
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
pucha, muy tranca tu explicacion bueno aunque domino dom no me sale muy bien que digamos si puedes profundizar seria excelente
Es un fume pero logre entenderlo…
Venezuela si puede!!!!!!
Programadores al poder 😀
Para quienes quieren el código fuente, se puede descargar desde: http://www.caricatos.net/articulos/check_form.zip
Saludos 😉
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.
Hay algún ejemplo similar pero para asp.
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.
buenas caricatos, exelente ejemplo que me sirvio para gstion de galeria de imagenes.
salu2
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 😉
muy bien caricatos pero como hago luego para guardar la imagen en un archivo especifico por ejmplo imagenes en mi sitio web.
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
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
gracias por el aporte me servira mucho
no crei que fuera tan compicado el codigo para evaluar archivos de imagen antes de enviarlo, pero el codigo es entendible, gracias, me sera de mucha ayuda en mi proyecto
Esta muy bueno este codigo,lo unico es que no funciona con mozilla porq no me permite previsualizar la imagen
En Google Chrome tampoco funciona.. mm x(
Excelente código, bastante entendible, aun estoy adaptándolo a un sitio. Me ha funcionado sin problemas en Firefox, IExplorer y Konqueror.
regaleme un codigo de fopen con anonimo para cuando suba una imagen(pero si la imagen no existe entonces que no aparezca el cuadrro en blanco)
<?php
for ($k=0;$k
<img src=".jpg” width=”97″ height=”70″ border=”0″/>
esta es l aforma com subo la imagen pero cuando agrego un campo nuevo en mi base dedatos no deberioa aparecerme una imagen o que me aparezaca una imagen como anonimo
excelente caricatos…. me estaba rompiendo la cabeza… y solo fue suficiente descargar tu archivo
Excelente Caricatos! pero en el caso de tener un multiupload como haces para previsualizar cada una de las imágenes ?
Saludos!
Caricatos.
El prtoblema que planteas es muy interesante pero no puedo extraer el codigo fuente del archivo check form .zip. Utilizo el winrap .
Puedes decirme la version de programa que hace la compactación.
deseo hacer lo mismo, pero con un boton button para que el usuario determine si desea ver la imagen o no
saludos
oviedo