Subidas de archivos en PHP 7

La carga de archivos es una funcionalidad común para muchas aplicaciones PHP. Tan común que PHP proporciona una variable global $_FILES conveniente que podemos usar para acceder a los archivos cargados, o errores detrás de los intentos de carga de archivos.

Echemos un vistazo al siguiente formulario de carga de archivos simple:

<form method="post" enctype="multipart/form-data">
<input type="file" name="photo" />
<input type="file" name="article" />
<input type="submit" name="submit" value="Upload" />
</form>

Para que PHP recoja los archivos, necesitamos establecer el valor del método de formulario para publicar y enctype para multipart/form-data. Una vez enviado, PHP lo recogerá y completará la variable $_FILES adecuadamente:

array(2) {
["photo"] => array(5) {
["name"] => string(9) "photo.jpg"
["type"] => string(10) "image/jpeg"
["tmp_name"] => string(14) "/tmp/phpGutI91"
["error"] => int(0)
["size"] => int(42497)
}
["article"] => array(5) {
["name"] => string(11) "article.pdf"
["type"] => string(15) "application/pdf"
["tmp_name"] => string(14) "/tmp/phpxsnx1e"
["error"] => int(0)
["size"] => int(433176)
}
}

Sin entrar en los detalles de la administración real de archivos posteriores a la carga, es suficiente decir que $_FILES contiene suficiente información para que podamos recoger y administrar más archivos, o indicar un posible código de error durante la carga. Se pueden devolver los siguientes ocho códigos de error:

  • UPLOAD_ERR_OK
  • UPLOAD_ERR_INI_SIZE
  • UPLOAD_ERR_FORM_SIZE
  • UPLOAD_ERR_PARTIAL
  • UPLOAD_ERR_NO_FILE
  • UPLOAD_ERR_NO_TMP_DIR
  • UPLOAD_ERR_CANT_WRITE
  • UPLOAD_ERR_EXTENSION

Si bien todos los errores deben abordarse por igual, dos de ellos (UPLOAD_ERR_FORM_SIZE y UPLOAD_ERR_PARTIAL) abren preguntas cruciales de rendimiento: ¿qué tan grande puede cargar un archivo y hay algún tiempo de espera en el proceso?
La respuesta a estas dos preguntas se puede encontrar en las directivas de configuración, algunas de las cuales están directamente relacionadas con la carga de archivos, mientras que otras están relacionadas con opciones PHP más generales:

  • session.gc_maxlifetime: este es el número de segundos después de los cuales los datos serán vistos como basura y limpiados; su valor predeterminado es 1.440 segundos
  • session.cookie_lifetime: esta es la vida útil de la cookie en segundos; de forma predeterminada, la cookie es válida hasta que se cierra el navegador
  • max_input_time: este es el tiempo máximo en segundos que un script puede analizar datos de entrada, como POST; por defecto, esto está desactivado
  • max_execution_time: este es el tiempo máximo que se permite ejecutar un script antes de que finalice; el valor predeterminado es 30 segundos
  • upload_max_filesize: este es el tamaño máximo de un archivo cargado; su valor predeterminado es 2 megabytes (2M)
  • max_file_uploads: este es el número máximo de archivos que se permite cargado en una sola solicitud
  • post_max_size: este es el tamaño máximo de los datos de publicación permitidos; su valor predeterminado es de 8 megabytes (8M)

Ajustar estas opciones asegura que evitemos los tiempos de espera y los límites de tamaño planificados. Para garantizar que podamos evitar la limitación de tamaño máximo de archivo al principio del proceso, MAX_FILE_SIZE se puede usar como un campo de formulario oculto:

<form method="post" enctype="multipart/form-data">
<input type="hidden" name="MAX_FILE_SIZE" value="100"/>
<input type="file" name="photo"/>
<input type="file" name="article"/>
<input type="submit" name="submit" value="Upload"/>
</form>

El campo MAX_FILE_SIZE debe preceder a cualquier otro campo de archivo que pueda tener un formulario. Su valor representa el tamaño máximo de archivo aceptado por PHP.
Intentar cargar un archivo más grande que el definido por el campo oculto MAX_FILE_SIZE ahora daría como resultado una variable $_FILES similar a la que se muestra aquí:

array(2) {
["photo"] => array(5) {
["name"] => string(9) "photo.jpg"
["type"] => string(0) ""
["tmp_name"] => string(0) ""
["error"] => int(2)
["size"] => int(0)
}
["article"] => array(5) {
["name"] => string(11) "article.pdf"
["type"] => string(0) ""
["tmp_name"] => string(0) ""
["error"] => int(2)
["size"] => int(0)
}
}

Podemos ver que el error ahora se ha convertido en el valor 2, que es igual a la constante UPLOAD_ERR_FORM_SIZE.
Si bien normalmente abordaríamos las limitaciones de la configuración predeterminada a través de la optimización del código, las cargas de archivos son específicas; en eso, realmente necesitamos asegurarnos de que las cargas de archivos grandes sean posibles si es necesario.

Comparte