Subiendo archivos a Google Drive con PHP

Comments: 9

Google Drive, el popular servicio de almacenamiento online de Google, dispone de una API que nos permite trabajar con diferentes lenguajes de programación para poder gestionar todos los ficheros almacenados desde nuestra propia aplicación. En este artículo muestro un sencillo ejemplo de como subirlos a nuestra cuenta por medio de PHP.

Siguiendo el mismo método que en artículos anteriores, para poder desarrollar el ejemplo he construido una sencilla aplicación la cual podéis encontrar en GitHub. Este ejemplo consta de un archivo index.php que contiene todo el código de la aplicación y desde donde también se llama a la librería de google (carpeta google-api-php-client) y a la vista HTML (fichero index.phtml). En la vista simplemente se muestran todos los archivos contenidos en la carpeta files. Todos los archivos que coloquemos en esta carpeta serán los que van a ser subidos a nuestra cuenta de Drive.

Este artículo está basado en el tutorial publicado por Google, aunque como podréis observar he modificado unos cuantos puntos para facilitar su compresión.

file upload php google drive

Antes de meternos con el código, debemos habilitar la API para nuestra aplicación. Para ello debemos crear un nuevo proyecto en la Consola de APIs de Google y seguir los pasos indicados en el primer punto del tutorial. Debemos tener en cuenta que en la sección services de la consola existen dos servicios relacionados con Drive: el SDK y la API. Debemos habilitar ambos, cosa que por defecto no sucede, y de no hacerlo obtendriamos un error de tipo HTTP 403 "Access Not Configured Error". Todo esto no lo comentan en el tutorial.

Una vez que hemos obtenido las claves de nuestro id y secreto de usuario nos descargamos la última versión de la librería de la API para PHP. Esta librería es la que he alojado dentro de la carpeta google-api-php-client.

Ahora sí, pasamos a estudiar el código. Empezaremos por la vista:

<!-- index.phtml -->

<!DOCTYPE html>
<html lang="es">
  <head>
        <meta charset="UTF-8">
        <title>Google Drive Example App</title>
    </head>
    <body>
        <ul>
            <?php foreach ($files as $file) { ?>
            <li><?php echo $file; ?></li>
            <?php } ?>
        </ul>
        <form method="post" action="<?php echo $url; ?>">
            <input type="submit" value="enviar" name="submit">
        </form>
    </body>
</html>

Aquí simplemente mostramos una lista con los nombres de todos los archivos contenidos en la carpeta files. Al pinchar en el botón de envío del formulario subiremos todos a nuestra cuenta de Google Drive. Al acceder a la página por primera vez seremos redirigidos a la página de Google donde tendremos que dar permiso a la API para que pueda acceder y gestionar los archivos alojados en nuestra cuenta. Una vez que pinchemos en "permitir acceso" seremos redirigidos de nuevo a nuestra aplicación.

Y a continuación nuestro código php:

// index.php

<?php
session_start();
$url_array = explode('?', 'http://'.$_SERVER ['HTTP_HOST'].$_SERVER['REQUEST_URI']);
$url = $url_array[0];
require_once 'google-api-php-client/src/Google_Client.php';
require_once 'google-api-php-client/src/contrib/Google_DriveService.php';
$client = new Google_Client();
$client->setClientId('your client id');
$client->setClientSecret('your client secret');
$client->setRedirectUri($url);
$client->setScopes(array('https://www.googleapis.com/auth/drive'));
if (isset($_GET['code'])) {
    $_SESSION['accessToken'] = $client->authenticate($_GET['code']);
    header('location:'.$url);exit;
} elseif (!isset($_SESSION['accessToken'])) {
    $client->authenticate();
}
$files= array();
$dir = dir('files');
while ($file = $dir->read()) {
    if ($file != '.' && $file != '..') {
        $files[] = $file;
    }
}
$dir->close();
if (!empty($_POST)) {
    $client->setAccessToken($_SESSION['accessToken']);
    $service = new Google_DriveService($client);
    $finfo = finfo_open(FILEINFO_MIME_TYPE);
    $file = new Google_DriveFile();
    foreach ($files as $file_name) {
        $file_path = 'files/'.$file_name;
        $mime_type = finfo_file($finfo, $file_path);
        $file->setTitle($file_name);
        $file->setDescription('This is a '.$mime_type.' document');
        $file->setMimeType($mime_type);
        $service->files->insert(
            $file,
            array(
                'data' => file_get_contents($file_path),
                'mimeType' => $mime_type
            )
        );
    }
    finfo_close($finfo);
    header('location:'.$url);exit;
}
include 'index.phtml';

Vamos a estudiar este código por partes:

session_start();
$url_array = explode('?', 'http://'.$_SERVER ['HTTP_HOST'].$_SERVER['REQUEST_URI']);
$url = $url_array[0];
require_once 'google-api-php-client/src/Google_Client.php';
require_once 'google-api-php-client/src/contrib/Google_DriveService.php';

Primero abrimos una sesión, la cual será necesaria para no tener que estar confirmando los permisos de la API cada vez que recargamos la página. A continuación defino la url de nuestra app y en caso de que contenga una varibale de tipo $_GET (enviada por Google al confirmar los permisos), la obviamos. Por último llamo a las dos librerías de Google: la clase Google_Client nos permitirá configurar nuestra cuenta de usuario y Google_DriveService nuestra cuenta de Drive.

$client = new Google_Client();
$client->setClientId('your client id');
$client->setClientSecret('your client secret');
$client->setRedirectUri($url);
$client->setScopes(array('https://www.googleapis.com/auth/drive'));

Definimos nuestra cuenta de usuario de la API de Google. Aquí es donde tendremos que introducir nuestro id y secreto de usuario obtenidos previamente.

if (isset($_GET['code'])) {
    $_SESSION['accessToken'] = $client->authenticate($_GET['code']);
    header('location:'.$url);exit;
} elseif (!isset($_SESSION['accessToken'])) {
    $client->authenticate();
}

Como comentaba más arriba, cuando confirmamos la petición de acceso de la API somos rederigidos de nuevo a nuestra aplicación y se nos pasa vía GET la varibale "code". Si existe, se la pasamos como parámetro al método authenticate del objeto Google_Client que devuelve un valor para el que abrimos nuestra sesión. Al contrario de lo que pudiera parecer, este valor devuelto contiene un JSON que a su vez contiene 6 valores, uno de las cuales es el "acces_token" como tal.

Por el contrario, cuando accedemos a la aplicación por primera vez, llamamos al método sin pasarle parámetro alguno y somos redirigidos a la pantalla de confirmación de permisos de acceso de la API.

$files= array();
$dir = dir('files');
while ($file = $dir->read()) {
    if ($file != '.' && $file != '..') {
        $files[] = $file;
    }
}
$dir->close();
if (!empty($_POST)) {
    $client->setAccessToken($_SESSION['accessToken']);
    $service = new Google_DriveService($client);
    $finfo = finfo_open(FILEINFO_MIME_TYPE);
    $file = new Google_DriveFile();
    foreach ($files as $file_name) {
        $file_path = 'files/'.$file_name;
        $mime_type = finfo_file($finfo, $file_path);
        $file->setTitle($file_name);
        $file->setDescription('This is a '.$mime_type.' document');
        $file->setMimeType($mime_type);
        $service->files->insert(
            $file,
            array(
                'data' => file_get_contents($file_path),
                'mimeType' => $mime_type
            )
        );
    }
    finfo_close($finfo);
    header('location:'.$url);exit;
}
include 'index.phtml';

Por último, guardamos en un array los nombres de los ficheros contenidos en nuestra carpeta files. Será este array el que utilicemos para subir y también mostrar en la vista (incluída al final del script) todos nuestros archivos.

Si hemos enviado el formulario pasamos a subir todos los archivos a Drive, a los cuales podemos definir sus propiedades de tí tulo, descripción y tipo de contenido a través de una instancia de la clase Google_DriveFile. Para ello hemos de pasar antes como parámetro el JSON con toda la información del token de acceso guardado en nuestra sesión e instanciamos la clase Google_DriveService a la que le pasamos como dependencia el objeto $client previamente configurado.

Comments

You must sing in to post a comment.

Blueprinter

Thank for posting this example code. It was a great help. I did need to make a few changes. You have two files that are both named 'index', but with different extensions. While testing locally, Apache won't render a .phtml file. I had to change the extension to .php. But then I had two index.php files. So I named the file with the HTML, main.php. Also, setting the redirect URI for testing locally, I used: http://localhost/FileUpload/main.php I had created a new folder name 'FileUpload' for this project. I had to leave the Javascript Origins as: http://localhost

Juan Carlos Bonifacio Guerra Juan Carlos Bonifacio Guerra

Hola Eduardo,

Me parece interesante la aplicación que compartes, Yo por el contrario, estoy buscando extraer un listado de todos los archivos que tengo en mi google drive, y quizás añadir el enlace de descarga a cada uno de los archivos. No se si puedes darme una mano, básicamente me agradaría obtener los siguientes campos: nombre carpeta, dirección de la carpeta, nombre del archivo, url del archivo y id del archivo. Sobre todo el "id" de los archivos, esto me es relevante para generar los enlaces de descarga.

Saludos.

Mario Alvarado Mario Alvarado

Hay alguna forma de que no te rediriga a iniciar sesión a google drive, sino que inicie sesion automáticamente a esta?. lo comento ya que estoy haciendo un sistema en donde hay múltiples usuarios, los cuales subirán archivos distintos, entonces, encuentro muy mala seguridad que todos tengan que saber el correo y la clave asociada a la cuenta de drive. debido a que alguno de estos puede ingresar con malas intenciones a la cuenta para borrar carpetas o archivos importantes.

lo agradeceria mucho, y muy buen post, me ha sido de mucha ayuda.

Eduardo Casas Eduardo Casas

Mario, como verás este artículo va a cumplir los 5 años por lo que es más que probable que muchos aspectos de la API de Google hayan cambiado.

Respecto a lo que comentas, supongo que habrá alguna forma pero como verás hace tiempo que dejé de trabajar con su API. Lamento no poder ayudarte.

Aleksej Aleksej

API Google has not changed, the code works fine. Thank you for the article.

Cristian Geovanny Gomez Duque Cristian Geovanny Gomez Duque

Buen día.
Excelente aporte Eduardo, te hago una pregunta, es posible parametrizar a que cuenta de google drive se subas los archivos, como mandar en alguna parte el correo y la contraseña de la cuenta para que permita la subida de archivos a varias cuentas?
Gracias