Cargas de ficheros por método POST
Esta funcionalidad permite a las personas subir tanto texto como ficheros binarios. Con las funciones de identificación y manipulación de ficheros de PHP, se tiene el control total para definir quién tiene derecho a subir, pero también qué se hará con el fichero una vez que se haya subido.
PHP es capaz de recibir ficheros emitidos por un navegador conforme a la norma RFC-1867.
Nota:
Notas de configuración
Véase también las directivas
file_uploads,
upload_max_filesize,
upload_tmp_dir,
post_max_size y
max_input_time en php.ini
PHP también soporta la carga por el método PUT como en el navegador Netscape Composer y Amaya del W3C. Consulte el capítulo sobre el
soporte del método PUT.
Ejemplo #1 Formulario de carga de fichero
Un formulario de carga de ficheros puede ser construido creando un formulario específico como este:
<!-- El tipo de codificación de datos, enctype, DEBE ser especificado como se indica a continuación -->
<form enctype="multipart/form-data" action="_URL_" method="post">
<!-- MAX_FILE_SIZE debe preceder al campo input de tipo file -->
<input type="hidden" name="MAX_FILE_SIZE" value="30000" />
<!-- El nombre del elemento input determina el nombre en el array $_FILES -->
Envíe este fichero: <input name="userfile" type="file" />
<input type="submit" value="Enviar el fichero" />
</form>
_URL_
en el ejemplo anterior debe ser reemplazado y apuntar a un fichero PHP.
El campo oculto MAX_FILE_SIZE
(medido en bytes) debe preceder al campo input de tipo file y su valor representa el tamaño máximo aceptado del fichero por PHP. Este elemento de formulario debe ser siempre utilizado, ya que permite informar al usuario que la transferencia deseada es demasiado grande antes de llegar al final de la carga. Tenga en cuenta que este parámetro puede ser "engañado" fácilmente desde el lado del navegador, por lo que no se debe confiar en él, tratándose finalmente de una funcionalidad de conveniencia del lado del cliente. El parámetro PHP (del lado del servidor) sobre el tamaño máximo de un fichero cargado, no puede ser engañado.
Nota:
Asegúrese de que su formulario de carga de fichero contenga enctype="multipart/form-data"
, de lo contrario, el fichero no será cargado.
La variable global $_FILES contendrá toda la información sobre el fichero cargado. Su contenido se detalla en nuestro ejemplo a continuación. Tenga en cuenta que se supone que el nombre de la variable del fichero cargado es userfile, tal como se define en el formulario anterior, pero puede ser cualquier nombre.
- $_FILES['userfile']['name']
-
El nombre original del fichero, tal como en la máquina del cliente web.
- $_FILES['userfile']['type']
-
El tipo MIME del fichero, si el navegador ha proporcionado esta información. Por ejemplo, esto podría ser "image/gif"
. Este tipo mime no es verificado por PHP y, por lo tanto, no se debe tomar su valor para sincronizarse.
- $_FILES['userfile']['size']
-
El tamaño, en bytes, del fichero cargado.
- $_FILES['userfile']['tmp_name']
-
El nombre temporal del fichero que será cargado en la máquina servidor.
- $_FILES['userfile']['error']
-
El código de error asociado a la carga del fichero.
- $_FILES['userfile']['full_path']
-
La ruta completa tal como se envía por el navegador. Este valor no contiene siempre una verdadera jerarquía de carpetas, y no se debe confiar en él. Disponible a partir de PHP 8.1.0.
El fichero cargado será almacenado temporalmente en el directorio temporal del sistema, a menos que se proporcione otro directorio con la directiva upload_tmp_dir del php.ini. El directorio por defecto del servidor puede ser cambiado en el entorno a través de la variable TMPDIR. Modificar el valor de esta variable con la función putenv() en un script PHP será sin efecto. Esta variable de entorno también puede ser utilizada para asegurarse de que otras operaciones funcionen también en los ficheros cargados.
Ejemplo #2 Validación de carga de ficheros
Véase también las funciones is_uploaded_file() y move_uploaded_file() para más información. El siguiente ejemplo cargará un fichero desde un formulario.
<?php
$uploaddir = '/var/www/uploads/';
$uploadfile = $uploaddir . basename($_FILES['userfile']['name']);
echo '<pre>';
if (move_uploaded_file($_FILES['userfile']['tmp_name'], $uploadfile)) {
echo "El fichero es válido, y ha sido cargado con éxito. Aquí hay más información :\n";
} else {
echo "Ataque potencial por carga de ficheros. Aquí hay más información :\n";
}
echo 'Aquí hay algunas informaciones de depuración :';
print_r($_FILES);
echo '</pre>';
?>
El script PHP que recibe el fichero cargado debe poder gestionar el fichero de manera apropiada. Se puede utilizar la variable $_FILES['userfile']['size'] para recalar todos los ficheros que son demasiado grandes o demasiado pequeños. Se puede utilizar la variable $_FILES['userfile']['type'] para descartar los ficheros que no tienen el tipo correcto, pero utilizarla únicamente para una serie de verificaciones, ya que este valor está completamente bajo el control del cliente y no es verificado por PHP. Se puede utilizar la información en $_FILES['userfile']['error'] y adaptar su política en función de los códigos de error. Sea cual sea su política, se debe borrar el fichero del directorio temporal o moverlo.
Si no se selecciona ningún fichero en el formulario, PHP devolverá 0
en $_FILES['userfile']['size'] y nada en $_FILES['userfile']['tmp_name'].
El fichero será borrado automáticamente del directorio temporal al final del script, si no ha sido movido o renombrado.
Ejemplo #3 Envío de un array de ficheros
PHP soporta los arrays en HTML así como con los ficheros.
<form action="" method="post" enctype="multipart/form-data">
<p>Imágenes:
<input type="file" name="pictures[]" />
<input type="file" name="pictures[]" />
<input type="file" name="pictures[]" />
<input type="submit" value="Enviar" />
</p>
</form>
<?php
foreach ($_FILES["pictures"]["error"] as $key => $error) {
if ($error == UPLOAD_ERR_OK) {
$tmp_name = $_FILES["pictures"]["tmp_name"][$key];
// basename() puede prevenir los ataques "filesystem traversal";
// otra validación/limpieza del nombre de fichero puede ser apropiada
$name = basename($_FILES["pictures"]["name"][$key]);
move_uploaded_file($tmp_name, "data/$name");
}
}
?>
La barra de progreso de carga puede ser implementada utilizando la progresión de la carga a través de las sesiones.