Verificar tipos de archivos subidos al servidor con php
Los formularios HTML son puntos de entrada a nuestra aplicación Web, y por lo tanto a nuestro servidor. Una persona malintencionada podría utilizar los elementos de nuestros formularios para almacenar contenido peligroso en nuestra base de datos, o en forma de fichero en algún directorio.
El formulario nos permite especificar cuál es el método HTTP utilizado para enviar los datos del formulario al servidor, utilizando el atributo method. Si deseamos subir un archivo será necesario indicar POST como método HTTP (aunque algunos navegadores también admiten PUT).
Para subir archivos debemos incluir en el formulario HTML un elemento <input> de tipo «file» (con el atributo type=»file»). Un ejemplo de formulario sería:
<form action="guardar_archivo.php" method="post" enctype="multipart/form-data">
<input type="file" name="mi_archivo" />
<input type="submit" value="Subir archivo" accept="image/jpeg" />
</form>
El elemento html «input file» permite seleccionar un archivo cualquiera del equipo cliente desde el cual se accede al formulario. Al hacer clic sobre el botón «submit» el navegador enviará al servidor el contenido de nuestro formulario, incluyendo el archivo seleccionado.
Aunque el atributo «accept» no debería utilizarse como instrumento para validar el tipo de archivo, sí es interesante añadirlo, ya que los buscadores (Firefox, Chrome, IE, …) pueden hacer uso de él para ofrecer un interfaz de usuario más apropiado, en función del tipo de archivo a seleccionar. Así por ejemplo, si añadimos el valor «image/jpeg«, como es nuestro ejemplo, el navegador podría ofrecer al usuario la posibilidad de obtener la imagen de la cámara local o seleccionarla de su colección de fotos.
El script que recibe el formulario es, en nuestro ejemplo, guardar_archivo.php, el especificado por el atributo action del elemento <form>.
En este archivo php podremos programar la validación del formulario (¿contiene el formulario los datos esperados?), así como el almacenamiento del archivo en el servidor.
En PHP, para acceder al archivo subido al servidor a través de un formulario, utilizaremos la variable superglobal $_FILES, un array asociativo en el que encontraremos la información que necesitamos para validar el fichero y almacenarlo. Accederemos a esta información utilizando como índice el nombre que le dimos al elemento input de tipo file, en nuestro caso $_FILES[‘mi_archivo’]. Así por ejemplo:
- En $_FILES[‘mi_archivo’][‘error’], obtendremos el valor 0 si el archivo se subió correctamente, o un valor entero mayor que cero si hubo error.
- En $_FILES[‘size’] el tamaño del fichero en número de bytes.
- En $_FILES[‘tmp_name’] la ruta del servidor en la que temporalmente se ha almacenado el fichero subido.
Los códigos de error que puede devolver $_FILES[‘mi_archivo’][‘error’] son:
- 1 → El fichero seleccionado excede el tamaño máximo permitido en php.ini (podemos saber el tamaño máximo permitido usando la función ini_get(‘upload_max_filesize’)).
- 2 → El archivo subido excede la directiva MAX_FILE_SIZE, si se especificó en el formulario.
- 3 → El archivo subido fue sólo parcialmente cargado.
- 4 → No se ha subido ningún archivo.
- 6 → Falta el directorio de almacenamiento temporal.
- 7 → No se puede escribir el archivo (posible problema relacionado con los permisos de escritura).ç
- 8 → Una extensión PHP detuvo la subida del archivo.
En el siguiente enlace podemos encontrar detalles sobre estos códigos de error, y ejemplos sobre su tratamiento:
https://www.php.net/manual/en/features.file-upload.errors.php
En el siguiente enlace hay un ejemplo sobre como especificar MAX_FILE_SIZE en el formulario:
https://www.php.net/manual/en/features.file-upload.post-method.php
Si no se ha producido ningún error, y no hemos especificado MAX_FILE_SIZE en el formulario, podríamos comprobar que el tamaño del archivo no supera un determinado límite, por ejemplo así:
if (round(intval($_FILES["mi_archivo"]["size"])/1048576, 2) > 2)
echo('El archivo no puede superar los 2 MB.');
Llegado a este punto, sólo nos queda validar el tipo de archivo, que después de todo era el objetivo de este artículo.
Validando el Tipo de Archivo:
Vamos a suponer que queremos subir archivos gráficos, cuyo formato sea png o jpg. Si se intenta subir cualquier otro tipo de archivo, devolveremos un mensaje de error.
Validando un archivo gráfico:
La ruta al archivo subido temporalmente al servidor la proporciona $_FILES[« mi_archivo «][«tmp_name»]. Conociendo la ruta utilizaremos la función de PHP exif_imagetype para determinar el tipo:
$mTmpFile = $_FILES["mi_archivo"]["tmp_name"];
$mTipo = exif_imagetype($mTmpFile);
if (($mTipo != IMAGETYPE_JPEG) and ($mTipo != IMAGETYPE_PNG))
echo("Formato de archivo no reconocido.");
Si el formato es el correcto podríamos pasar a validar las dimensiones del archivo gráfico. Por ejemplo, supongamos que deben ser exactamente 150 píxeles de alto y ancho:
list($mW, $mH) = getimagesize($mTmpFile);
if (($mW < 150)and($mH < 150))
echo('Las dimensiones de la imagen, '.$mW.' x '.$mH.' píxeles, no son las requeridas, 150 x 150 píxeles.');
buenos dias me parece muy interesante el codigo queria pedirles ayuda de como actualizar un imagen la inserccion funciona correctamente ahora lo que necesito es saber comoa atualizarlo ya que me sale un error archivo no permitido, es tipo de archivo prohibido o excede el tamano de $limite_kb Kilobytes espero me puedan ayudar
Hola Pablo,
Explique un poco mejor su problema por favor, sino será difícil que le podamos ayudar.
Dice que la insercción funciona … ¿la insercción en dónde? Se refiere a que guarda el archivo correctamente en el servidor, en una base de datos …. ?
Cuando habla de actualizar, qué tipo de operación está realizando, que funciones utiliza, …
¿Cuál es exactamente el mensaje de error?
La variable $limite_kb, ¿la ha declarado usted, dónde la usa, cómo … ?
Un saludo!
saludos.Gracias amigo por el articulo,me encanto la forma como validaste el tamaño del archivo.
Buenas tardes, estoy desarrollando un proyecto en el cual debo capturar una imagen o foto desde una camara web con un boton, el caso es que no doy con como subir la imagen a una carpeta local de mi servidor php (fotos) y guardar la ruta en mysql… Agradezco su pronta ayuda
hola una consulta porque es recomendable pasar los archivos a una carpeta del servidor y no guardarlo como formato blob directo a un campo en una tabla???