Upload de archivos con PHP

PHP en CableNaranja
PHP en CableNaranja

¡Comparte nuestro contenido!

En esta ocasión, aprenderemos a hacer upload de archivos con PHP, como siempre buscando hacerlo de manera sencilla y rápida, pero funcional e incluso un poco segura ¡Manos a la obra!

Preparando el formulario

Coloquemos un formulario sencillo, el método será de envío de datos será POST y el action lo haremos en el mismo documento gracias a la constante $PHP_SELF, la cual haremos pasar por la función htmlentities para evitar los típicos ataques XSS. Adicionalmente a eso usaremos el atributo enctype con el valor multipart/form-data para indicar que el formulario enviará datos en partes. Esto último es obligatorio para enviar archivos.

<form method="post" action="<?php echo htmlentities($PHP_SELF); ?>" enctype="multipart/form-data">
</form>

Dentro de nuestro formulario sólo contaremos un un input de tipo file y un botón submit.

<p><label>Envía una imagen (8MB Máx):</label><input type="file" name="imagen" /></p>
<p><input type="submit" value="Enviar" name="btnOK" /></p>

Procesando los datos del formulario

Abrimos nuestro bloque PHP justo debajo de lo anterior. Lo primero que necesitamos es verificar que la variable tipo POST del botón existe.

if(isset($_POST["btnOK"])){
}

Ahí dentro capturamos el archivo tipo file usando el array $_FILES que contiene los datos de nuestro input de tipo file. concretamente lo siguiente:

  1. name: Contiene el nombre del archivo.
  2. size: Contiene el tamaño físico del archivo en bytes.
  3. tmp_name: Contiene el nombre temporal que recibe en el sistema host.

Por ejemplo:

$fileName = $_FILES["imagen"]["name"];
$fileSize = $_FILES["imagen"]["size"];
$fileTemp = $_FILES["imagen"]["tmp_name"];

Ahora, verifiquemos que se haya enviado un archivo, la manera simple es verificar que el tamaño físico sea mayor a cero.

if($fileSize==0){
   echo "<p>Ningun archivo fue seleccionado. Intente otra vez.</p>";
}else{
   // De lo contrario...
}

Si hay un archivo, necesitamos extraer si extensión para verificar que sea una imagen. Primero extraigamos la extensión.

$extension = explode(".", $fileName);

Todavía nos sobra el punto, pero lo hemos separado en un array de dos valores: (0) . y (1) jpg – Por citar un ejemplo – Ahora eliminemos el punto.

$formato = $extension[1];

Y hagamos una lista de formatos soportados

$validos =  array("png", "jpg", "jpeg", "gif");

Ocupemos una variable que empiece en cero. Dado que vamos a revisar nuestro array de formatos soportados, esta variable sólo aumentará su valor si la extensión de nuestro archivo se encuentra en la lista.

$contarExt = 0;
for($e=0;$e<count($validos);$e++){
   if($formato==$validos[$e]) $contarExt++;
}

Si nuestra variable nunca pasó de cero, significa que el archivo no se encuentra dentro de los formatos válidos.

if($contarExt==0) echo "<p>No es un formato de imagen adecuado. Prueba con otro.</p>";
else{
   // De lo contrario
}

En caso contrario, lo siguiente que necesitamos, es verificar que no exceda el tamaño que establecimos. Como el tamaño de nuestro archivo se encuentra en bytes, necesitamos convertirlo en kilobytes, para ello simplemente lo dividimos entre 1024.

$tamInKBs = $fileSize / 1024;

Ahora, establecemos nuestro límite en 8192 KB – Por que 8192 / 1024 = 8MB –

$maxSize = 8192;

Y si el tamaño del archivo excede dicho límite…

if($tamInKBs > $maxSize) echo "<p>El archivo excede el tamaño permitido.</p>";
else{
   // De lo contrario...
}

Pero si el archivo tiene un tamaño permitido, entonces, definimos la ruta física el archivo

define('APP_PATH', dirname(__FILE__));

Y le ponemos el separador apropiado de acuerdo al sistema operativo de nuestro host

$ruta = APP_PATH . DIRECTORY_SEPARATOR;

Le agregamos el nombre físico del archivo con la funcion basename

$subir = $ruta . basename($fileName);

Si todo salió bien, movemos el archivo temporal a la ruta física que hemos creado.

if(move_uploaded_file($fileTemp, $subir)){
   echo "<p>¡Imagen recibida, gracias!</p>";
}else echo "<p>Hubo un problema al intentar subir la imagen.</p>";

Es importante notar, que no hicimos validación del formato del archivo por medio de su MIME type, ya que como se menciona en Acunetix, realmente es muy fácil para un atacante ignorar esa validación.

Actualizar el servidor y probar el ejemplo

Necesitamos actualizar el límite de subida de archivos en PHP, para ello buscamos el archivo php.ini y lo abrimos para su edición. Buscamos 3 valores principalmente upload_max_filesize que actualizaremos con el límite que establecimos en nuestro código.

upload_max_filesize = 8M

Luego, post_max_size que debe tener al menos 50% más que el valor anterior, por ejemplo

post_max_size = 12M

Por último, verificamos que memory_limit tenga asignada suficiente memoria, en PHP 7 el valor mínimo es 128, recomendable para la mayoría de casos

memory_limit = 128M

Reiniciemos nuestro servidor, y probemos el ejemplo (fullscreen para ver el video)

En sistemas Linux / Unix, será necesario ajustar los permisos de la carpeta.

Descarga el ejemplo

Como siempre, puedes probar el código descargando el código fuente completo. Si tienes alguna duda o sugerencia, puedes dejarla en la caja de comentarios.

¡Comparte nuestro contenido!

Israel García

Docente, IT Manager, Blogger & Developer. Escribo por diversión, educo por pasión. | Grandstanding is not my thing.

Podría también gustarte...

1 Respuesta

  1. septiembre 13, 2018

    […] de llegar a nuestro objetivo, vamos a retomar también algunos conceptos que vimos en el artículo: Como hacer upload de archivos con PHP ¡Manos a la […]

Deja un comentario

Tu dirección de correo electrónico no será publicada. Los campos obligatorios están marcados con *

shares