Subida de ficheros
PHP Manual

Subida con el método POST

Esta característica permite la subida de ficheros de texto y binarios. Con la autenticación de PHP y las funciones de manipulación de ficheros se tiene control completo sobre quién está autorizado a realizar una subida y qué hay que hacer con el fichero una vez subido.

PHP es capaz de recibir subidas de ficheros de cualquier navegador compatible con el RFC-1867.

Nota: Nota sobre configuraciones relacionadas

Véanse también las directivas file_uploads, upload_max_filesize, upload_tmp_dir, post_max_size y max_input_time de php.ini

PHP también admite el método PUT para subir ficheros tal y como lo utilizan los clientes Netscape Composer y Amaya del W3C. Véase el Soporte para el método PUT para más detalles.

Ejemplo #1 Formulario para la subida de ficheros

Se puede construir una página de subida de ficheros creando un formulario especial parecido a este:

<!-- El tipo de codificación de datos, enctype, DEBE especificarse como sigue -->
<form enctype="multipart/form-data" action="__URL__" method="POST">
    <!-- MAX_FILE_SIZE debe preceder al campo de entrada del fichero -->
    <input type="hidden" name="MAX_FILE_SIZE" value="30000" />
    <!-- El nombre del elemento de entrada determina el nombre en el array $_FILES -->
    Enviar este fichero: <input name="fichero_usuario" type="file" />
    <input type="submit" value="Enviar fichero" />
</form>

El __URL__ del ejemplo anterior se debe sustituir y debe apuntar a un fichero de PHP.

El campo oculto MAX_FILE_SIZE (medido en bytes) debe preceder al campo de entrada del fichero, siendo su valor el tamaño de fichero máximo aceptado por PHP. Se debe utilizar siempre este elemento del formulario, ya que evita a los usuarios la molestia de esperar a que un fichero grande sea transferido sólo para descubrir que falló la transferencia porque era demasiado grande. Hay que tener en cuenta que engañar a esta configuración en el lado del navegador es muy fácil; nunca dependa de que los ficheros que tengan un tamaño mayor sean bloqueados por esta característica. Es simplemente una característica conventiene para los usuarios en el lado cliente de la aplicación. No obstante, la configuración de PHP (en el lado del servidor) para un tamaño máximo no puede ser engañada.

Nota:

Asegúrese de que el formulario de subida de ficheros tiene el atributo enctype="multipart/form-data" o de lo contrario la subida de ficheros no funcionará.

El array global $_FILES contendrá toda la información de los los ficheros subidos. Su contenido en el formulario del ejemplo es el siguiente. Observe que se asume el empleo del nombre fichero_usuario para el fichero subido, tal como se utiliza en el script de ejemplo anterior. Este puede ser cualquier nombre.

$_FILES['fichero_usuario']['name']

El nombre original del fichero en la máquina del cliente.

$_FILES['fichero_usuario']['type']

El tipo MIME del fichero, si el navegador proporcionó esta información. Un ejemplo sería "image/gif". Este tipo MIME, sin embargo, no se comprueba en el lado de PHP y por lo tanto no se garantiza su valor.

$_FILES['fichero_usuario']['size']

El tamaño, en bytes, del fichero subido.

$_FILES['fichero_usuario']['tmp_name']

El nombre temporal del fichero en el cual se almacena el fichero subido en el servidor.

$_FILES['fichero_usuario']['error']

El código de error asociado a esta subida.

Por defecto, los ficheros se almacenan en el directorio temporal predeterminado del servidor, a menos que se haya indicado otra ubicaicón con la directiva upload_tmp_dir en php.ini. Se puede cambiar el directorio predeterminado del servidor estableciendo la variable de entorno TMPDIR en el entorno en que se ejecuta PHP. Configurarlo usando putenv() desde un script de PHP no funcionará. Esta variable de entorno también se puede utilizar para asegurarse de que las demás operaciones están trabajando sobre los ficheros subidos.

Ejemplo #2 Validación de la subida de ficheros

Véanse también las entradas de las funciones is_uploaded_file() y move_uploaded_file() para más información. El siguiente ejemplo procesará la subida de fichero desde un formulario.

<?php
// En versiones de PHP anteriores a la 4.1.0, debería utilizarse $HTTP_POST_FILES en lugar
// de $_FILES.

$dir_subida '/var/www/uploads/';
$fichero_subido $dir_subida basename($_FILES['fichero_usuario']['name']);

echo 
'<pre>';
if (
move_uploaded_file($_FILES['fichero_usuario']['tmp_name'], $fichero_subido)) {
    echo 
"El fichero es válido y se subió con éxito.\n";
} else {
    echo 
"¡Posible ataque de subida de ficheros!\n";
}

echo 
'Más información de depuración:';
print_r($_FILES);

print 
"</pre>";

?>

El script de PHP que recibe el fichero subido debería implementar cualquier lógica necesaria para determinar qué se debe hacer con el fichero subido. Se puede, por ejemplo, utilizar la variable $_FILES['fichero_usuario']['size'] para descartar cualquier fichero que sea demasiado pequeño o demasiado grande. Se podría utilizar la variable $_FILES['fichero_usuario']['type'] para descartar cualquier fichero que no corresponda con un cierto criterio de tipo, aunque esto se debe emplear solo como la primera de una serie de comprobaciones debido a que este valor está completamente bajo el control del cliente y no se comprueba en el lado de PHP. También se puede usar $_FILES['fichero_usuario']['error'] y planear la lógica de acuerdo con los códigos de error. Cualquiera que sea la lógica, se debería borrar el fichero del directorio temporal o moverlo a otra ubicación.

Si no se selecciona ningún fichero en el formulario para realizar la subida, PHP devolverá $_FILES['fichero_usuario']['size'] como 0, y $_FILES['fichero_usuario']['tmp_name'] como ninguno.

El fichero será borrado del directorio temporal al final de la solicitud si este no ha sido movido o renombrado.

Ejemplo #3 Subir un array de ficheros

PHP admite la funcionalidad de array en HTML incluso con ficheros.

<form action="" method="post" enctype="multipart/form-data">
<p>Imágenes:
<input type="file" name="imágenes[]" />
<input type="file" name="imágenes[]" />
<input type="file" name="imágenes[]" />
<input type="submit" value="Enviar" />
</p>
</form>
<?php
foreach ($_FILES["imágenes"]["error"] as $clave => $error) {
    if (
$error == UPLOAD_ERR_OK) {
        
$nombre_tmp $_FILES["imágenes"]["tmp_name"][$clave];
        
// basename() puede evitar ataques de denegació del sistema de ficheros;
        // podría ser apropiado más validación/saneamiento del nombre de fichero
        
$nombre basename($_FILES["imágenes"]["name"][$clave]);
        
move_uploaded_file($nombre_tmp"datos/$nombre");
    }
}
?>

Se puede implementar una barra de progreso de subida de ficheros con el Progreso de subida en sesiones.


Subida de ficheros
PHP Manual