Para poder subir archivos en un formulario que va a ser tratado con PHP, necesitamos varios elementos:

  1. El formulario tiene que declara enctype=”multipart/form-data” . Esto permite enviar, además de los campos del formulario, el fichero adjunto.

  2. El formulario debe incluir al menos un input de tipo type=“file” .

  3. Al recepcionar el formulario, tenemos que comprobar si el campo contiene algún elemento file, realizando ciertas validaciones de que se ha recibido correctamente, y moverlo desde allí hacia la carpeta definitiva donde queramos almacenarlo (o será borrado automáticamente de la carpeta temporal pasado cierto tiempo).

Todo esto lo podemos conseguir con un código de ejemplo como éste:

<?php

echo '<html><head></head><body>';
echo '<h1>Ejemplo subida de fichero</h1>';
echo '<form method="post" enctype="multipart/form-data">';
echo 'Fichero a recibir: <input type="file" name="myfile" /><br />';
echo '<input type="submit" value="Enviar">';
echo '</form>';

if ( isset( $_FILES ) && isset( $_FILES['myfile'] ) && !empty( $_FILES['myfile']['name'] && !empty($_FILES['myfile']['tmp_name']) ) ) {
	//Hemos recibido el fichero
	//Comprobamos que es un fichero subido por PHP, y no hay inyección por otros medios
	if ( ! is_uploaded_file( $_FILES['myfile']['tmp_name'] ) ) {
		echo "Error: El fichero encontrado no fue procesado por la subida correctamente";
		exit;
	} 
	$source = $_FILES['myfile']['tmp_name'];
	$destination = __DIR__.'/upload/'.$_FILES['myfile']['name'];
			
	if ( is_file($destination) ) {
	 echo "Error: Ya existe almacenado un fichero con ese nombre";
	 @unlink(ini_get('upload_tmp_dir').$_FILES['myfile']['tmp_name']);
	 exit;
	}

	if ( ! @move_uploaded_file($source, $destination ) ) {
		echo "Error: No se ha podido mover el fichero enviado a la carpeta de destino";
		@unlink(ini_get('upload_tmp_dir').$_FILES['myfile']['tmp_name']);
		exit;
	}
	echo "Fichero subido correctamente a: ".$destination;
				
}

Algunas consideraciones adicionales:

  • Si queremos poder recibir varias veces ficheros con el mismo nombre, tendremos que renombrarlos al recibirlos para asegurarnos que no se sobreescribe.

  • El tamaño máximo que se puede recibir de fichero viene limitado por la configuración de Apache y PHP. Aunque aumentemos estos límites, ponerlos demasiado grandes puede traer consecuencias negativas a la estabilidad del servidor.

  • Es posible que aunque el sistema permita recibir ficheros de cierto tamaño, queramos permitir un tamaño menor, validando el fichero recibido antes de aceptarlo y moverlo a nuestra carpeta.

  • También es posible que queramos impedir que se suban ficheros con ciertas extensiones, permitiendo por ejemplo solo imágenes o ficheros PDF.

  • El sistema operativo de origen puede admitir una longitud de nombre de ficheros o caracteres que no es posible utilizar en el servidor. Puede ser necesaria una sanitización del nombre de fichero.