A raíz de mi trabajo en Bananity recientemente he estado trasteando con la subida de archivos al servidor (hasta ese momento nunca había tenido que tratar con eso) y el envío de archivos entre servidores. Y habiéndome parecido interesante lo aprendido estos dos días he creído conveniente comentarlo por aquí :) .

En primer lugar comentaré la parte más típica: cómo hacer un formulario en HTML que permita archivos y como recibir archivos desde PHP.

En segundo lugar comentaré la parte que a mí me ha parecido más interesante (aunque nada complicada): enviar archivos a otros servidores desde PHP.

Enviar archivos desde un formulario HTML

Enviar un archivo a un servidor web desde un formulario HTML es muy sencillo, resumiendo mucho: se tiene que usar el método POST, usar un elemento input de tipo file, y añadir la propiedad enctype al elemento form con el valor "multipart/form-data". Ejemplo:

1
2
3
4
<form method="post" enctype="multipart/form-data" action="http://sitiodeproceso">
    <input type="file" name="filetoupload">
    <input type="submit" value="Envia!">
</form>

Recibir archivos usando PHP

Muy bien, el visitante de nuestro sitio web ya nos ha enviado su archivo... ¿como lo procesamos para guardarlo? PHP nos provee de unas cuantas variables globales bastante útiles, entre las que se encuentra $_FILES, que es la que utilizaremos. El servidor se encargará de dejar el archivo subido en un directorio temporal, y $_FILES nos dará información sobre su ruta y posibles errores en el proceso de envío.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
<?php
 
// Notemos que uso como índice el nombre que le dí al elemento input
// en el formulario HTML
$fileinfo = $_FILES['filetoupload'];
 
// Obtenemos la ruta donde está guardado temporalmente el fichero
$filepath = $fileinfo['tmp_name'];
 
// Recuperamos el nombre que tenía el fichero cuando se envió
$filename = $fileinfo['name'];
 
// Movemos el fichero a donde creamos conveniente
move_uploaded_file ($filepath, '/ruta/donde/queremos/guardarlo/'.$filename);
 
?>

En este ejemplo no he tenido en cuenta la gestión de errores ni otros valores de $_FILES['filetoupload'] interesantes como type, error o size.

Enviar archivos con PHP (1ª opción: CURL)

Ahora sí, llegamos a la parte que me parecía más interesante :) , aunque empezaré por la "vía complicada": usar CURL. Este ejemplo lo he extraído de [1].

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
<?php
    $ch = curl_init();
    curl_setopt($ch, CURLOPT_HEADER, 0);
    curl_setopt($ch, CURLOPT_VERBOSE, 0);
    curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
    curl_setopt($ch, CURLOPT_USERAGENT, "AgenteQueNosVengaEnGana");
    curl_setopt($ch, CURLOPT_URL, 'http://urlhaciaotroservidor');
    curl_setopt($ch, CURLOPT_POST, true);
 
    // Igual que <input type="file" name="filetoupload">
    // Notad la @ antes del path, es clave.
    $post = array(
        "filetoupload"=>"@/path/to/myfile.jpg",
    );
 
    curl_setopt($ch, CURLOPT_POSTFIELDS, $post);
    $response = curl_exec($ch);
?>

La verdad es que puede ser un poco engorroso subir archivos siguiendo este procedimiento, no porque sea mucho código, sino porque se tienen que memorizar (o tener a mano) que parámetros debemos establecer y con que valores.

Evidentemente siempre nos queda la opción de encapsular un código similar a éste dentro de un método, pero a mi este "problema" me servirá como excusa para introducir una solución alternativa :D .

Enviar archivos con PHP (2ª vía: Requests)

Gracias a mi compañero Carles Iborra descubrí la biblioteca libre Requests, a la que actualmente estoy dando muchísimo uso, especialmente para realizar testeo unitario, aunque también para enviar archivos usando PHP. El siguiente ejemplo lo dice todo.

1
2
3
4
5
6
7
8
9
10
11
<?php
 
include('Requests.php');
Requests::register_autoloader();
 
$post = array(
    'filetoupload' => '@/path/to/file'
);
$request = Requests::post('http://dondeenviamoselarchivo', array(), $post);
 
?>

Referencias

  1. DTBAKER: Uploading a file using curl in PHP