viernes, 11 de septiembre de 2015

Upload de archivos con PHP


En PHP tenemos muchas funcionalidades desarrolladas desde el principio y sin necesidad de instalar ningún añadido en nuestro servidor. Es el caso de subir archivos a un servidor web por HTTP y a través de una página con un formulario, donde se permite seleccionar el archivo que queremos cargar de nuestro disco duro. 

El ejemplo se encuentra bien documentado en un montón de páginas para desarrolladores, sin ir más lejos en la página de la propia tecnología: http://www.php.net/manual/es/features.file-upload.php. Nosotros en este caso vamos a intentar ir un poco más allá, realizando un par de comprobaciones al subir el fichero y combinando en el mismo formulario campos de tipo file y tipo text. 

El formulario para subir seleccionar los archivos 

Es un formulario cualquiera, pero tiene una serie de particularidades y campos file, que no solemos utilizar habitualmente. 

<form action="subearchivo.php" method="post" enctype="multipart/form-data"> 
    <b>Campo de tipo texto:</b> 
    <br> 
    <input type="text" name="cadenatexto" size="20" maxlength="100"> 
    <input type="hidden" name="MAX_FILE_SIZE" value="100000"> 
    <br> 
    <br> 
    <b>Enviar un nuevo archivo: </b> 
    <br> 
    <input name="userfile" type="file"> 
    <br> 
    <input type="submit" value="Enviar"> 
</form>

Para empezar vemos que se ha colocado un nuevo atributo en el formulario: enctype="multipart/form-data", necesario para subir en un mismo formulario datos y archivos. 

También tenemos el campo hidden MAX_FILE_SIZE, que sirve para indicar el tamaño en bytes de los archivos a subir. Este campo algunos navegadores no tienen porqué entenderlo o hacerle caso. Además, es fácil saltarse esa protección, por lo que deberemos en las propias páginas PHP comprobar que el archivo tenga el tamaño que deseamos. 

Por último, tenemos el campo tipo file, donde se seleccionará el archivo a subir. También hemos colocado un campo de tipo text, para subir datos por POST de tipo texto acompañados a los datos binarios del archivo. 

Página que sube los archivos 

Esta página debe hacer las comprobaciones necesarias para saber si las características del archivo a subir son las que deseamos y realizar la copia del archivo en un directorio del servidor. 

Para hacer las comprobaciones, PHP nos crea una serie de variables que podemos acceder con la información del archivo enviado. 

$HTTP_POST_FILES['userfile']['name'] 
El nombre original del fichero en la máquina cliente. 

$HTTP_POST_FILES['userfile']['type'] 
El tipo mime del fichero (si el navegador lo proporciona). Un ejemplo podría ser "image/gif". 

$HTTP_POST_FILES['userfile']['size'] 
El tamaño en bytes del fichero recibido. 

$HTTP_POST_FILES['userfile']['tmp_name'] 
El nombre del fichero temporal que se utiliza para almacenar en el servidor el archivo recibido.

Nota: En este momento (a partir de PHP 5) el array $HTTP_POST_FILES ha sido sustituido por el array $_FILES. En realidad es exactamente lo mismo, con la diferencia que $_FILES es más corto de escribir. Dependiendo de la configuración de tu PHP el nombre de variable antigua $HTTP_POST_FILES puede existir o no, pero en cualquier caso te recomendamos utilizar $_FILES para que tus scripts funcionen en cualquier servidor, independientemente de la configuración. Por ejemplo, usa $_FILES['userfile']['tmp_name'] en lugar de $HTTP_POST_FILES['userfile']['tmp_name'].
<? 
//tomo el valor de un elemento de tipo texto del formulario 
$cadenatexto = $_POST["cadenatexto"]; 
echo "Escribió en el campo de texto: " . $cadenatexto . "<br><br>"; 

//datos del arhivo 
$nombre_archivo = $HTTP_POST_FILES['userfile']['name']; 
$tipo_archivo = $HTTP_POST_FILES['userfile']['type']; 
$tamano_archivo = $HTTP_POST_FILES['userfile']['size']; 
//compruebo si las características del archivo son las que deseo 
if (!((strpos($tipo_archivo, "gif") || strpos($tipo_archivo, "jpeg")) && ($tamano_archivo < 100000))) { 
    echo "La extensión o el tamaño de los archivos no es correcta. <br><br><table><tr><td><li>Se permiten archivos .gif o .jpg<br><li>se permiten archivos de 100 Kb máximo.</td></tr></table>"; 
}else{ 
    if (move_uploaded_file($HTTP_POST_FILES['userfile']['tmp_name'], $nombre_archivo)){ 
       echo "El archivo ha sido cargado correctamente."; 
    }else{ 
       echo "Ocurrió algún error al subir el fichero. No pudo guardarse."; 
    } 
} 
?>

Para empezar, recogemos el campo de texto enviado por POST, de la forma habitual. Aunque esto no tenga nada que ver con subir archivos, es muy normal que en el mismo formulario deseemos mezclar varios tipos de información. 

Luego se recogen los datos necesarios del archivo, como su nombre, extensión y tamaño para, en el siguiente if, comprobar que la extensión sea .gif o .jpg y que el tamaño menor que 100000 bytes. 

Si el archivo tenía las características deseadas, se puede subir al servidor. Para ello se utiliza la función move_uploaded_file(), que recibe el nombre del archivo temporal que se desea subir y el nombre del archivo que se desea dar. 

Cuando se sube el archivo, el servidor lo copia en una localización temporal para que seamos nosotros los que elijamos la posición definitiva donde queremos que se almacene. Si no lo copiamos a ningún sitio, después de la ejecución de la página, se borra de su localización temporal. 

La función move_uploaded_file() se utiliza para mover el archivo a la posición definitiva. Recibe por un lado el nombre temporal del fichero y por otro el nombre que deseamos colocarle definitivamente y, si se desea, la ruta para llegar al directorio donde queremos guardarlo. En el caso del ejemplo sólo se indica el nombre del archivo, por ello el fichero se subirá al mismo directorio donde están las páginas PHP que hacen el upload. Esta función devuelve un boleano que indica si hubo o no éxito al subir el archivo. 


Nota: Es importante señalar que el upload de archivos es un proceso crítico que puede dar lugar a errores y agujeros de seguridad. Por ejemplo, si los directorios destino están protejidos contra escritura, nos dará un error. Podemos ver los errores comunes relatados en la página de PHP.

No hay comentarios:

Publicar un comentario

Entradas populares