Tabla de contenidos
En ocasiones necesitamos usar servicios para alojar tus archivos o documentos en línea en la nube. Existen muchos servicios que ofrecen como Google Drive o Dropbox. Estos servicios ofrecen su API para web (o para otros entornos y lenguajes de programación). El que servicio que vamos a utilizar es es Google Drive, que pertenece a Google y es uno de los mejores servicios junto a otros para crear, eliminar, exportar, listar, etc. archivos en su plataforma.
¿Qúe es una API?
Una API es un conjunto de definiciones y protocolos que se utilizan para desarrollar e integrar el software de las aplicaciones. API significa interfaz de programación de aplicaciones.
Las API permiten que sus productos y servicios se comuniquen con otros, sin necesidad de saber cómo están implementados. Esto simplifica el desarrollo de las aplicaciones y permite ahorrar tiempo y dinero. Las API le otorgan flexibilidad; simplifican el diseño, la administración y el uso de las aplicaciones, y proporcionan oportunidades de innovación, lo cual es ideal al momento de diseñar herramientas y productos nuevos (o de gestionar los actuales).
Si queréis más información os dejo el siguiente enlace.
¿Qué APIS tiene Google?
Pues tienen API de cualquier producto de Google. Los más demandados son de Google Cloud, Google Maps, Android, Google Analytics, etc.
En este POST, vamos a ver el proceso de subir documentos a Google Drive con PHP utilizando la API de Google, por lo que vamos a mostrar cómo hacerlo paso a paso.
Explicación paso a paso
Configuración del servicio
Vamos a la web de Google API Console y pulsamos a «Nuevo Proyecto»
En el buscador, buscamos la API «Google Drive API» y la habilitamos.
En el menú que se encuentra a la izquierda de Google Drive API, pulsamos a Credenciales.
Pulsamos a Crear credenciales y nos saldrá un desplegable, por lo que tenemos que seleccionar «Cuenta de servicio».
Rellenamos los datos del formulario, introducimos los datos para nuestra API:
Nombre de cuenta de servicio: lacodigoteca
ID de cuenta de servicio: lacodigoteca
Descripción de la cuenta de servicio: La codigoteca
Ahora vamos a asignar permisos en la cuenta de la API. En este caso, vamos a darle permisos de Propietario.
Pulsamos al correo electrónico que nos ha creado el servicio, y pulsamos añadir clave.
Al pulsar a añadir Clave, nos va a preguntar cómo queremos nuestra clave privada, en formato JSON o en P12. Vamos a seleccionar a JSON.
Nos va descargar un fichero JSON en nuestro ordenador, en el que vamos a utilizar después.
Permisos en nuestro Google Drive
Nos dirigimos a nuestro Google Drive y creamos una carpeta, en mi caso se llamará «lacodigoteca». Accedemos dentro de la carpeta y pulsamos a «Compartir»
Añadimos el correo del servicio y le damos permisos de Editor.
Restringiremos el acceso a la carpeta y copiaremos el enlace a compartir.
En el enlace a compartir podemos ver cuál es el ID, os dejo un enlace de ejemplo con el ID en negrita.
https://drive.google.com/drive/folders/1qKTBAOXqB3d90OSubbp6Nvh10CQdFpXb?usp=sharing
Instalación de la librería Google API para PHP.
Nos dirigimos al repositorio de la librería Google API para PHP https://github.com/googleapis/google-api-php-client/releases
Descargamos la última versión y descargamos el fichero ZIP con la versión de PHP que estamos utilizando en nuestro proyecto web. Con ello extraemos la carpeta y la dejamos en el directorio raíz de nuestro proyecto.
Archivo PHP (paso a paso)
Añadimos el archivo de la API a nuestro fichero .php
<?
include_once 'google-api-php-client-v2.7.2-PHP7.4/vendor/autoload.php';
Creamos una función en el que nos servirá para subir documentos a Google Drive:
En la variable $claveJSON indicaremos cual es la ID de la carpeta de Google Drive que hemos creado anteriormente.
En la variable $pathJSON , tenemos que poner el nombre del fichero JSON, que es el que tiene la clave para utilizar el servicio. El fichero JSON lo tengo alojado en la raíz del proyecto.
function subirDocumentoDrive($documento,$descripcion){
// Variables de credenciales.
$claveJSON = '1qKTBAOXqB3d90OSubbp6Nvh10CQdFpXb';
$pathJSON = 'lacodigoteca-87cea347411f.json';
//configurar variable de entorno
putenv('GOOGLE_APPLICATION_CREDENTIALS='.$pathJSON);
$client = new Google_Client();
$client->useApplicationDefaultCredentials();
$client->setScopes(['https://www.googleapis.com/auth/drive.file']);
try{
//instanciamos el servicio
$service = new Google_Service_Drive($client);
//instacia de archivo
$file = new Google_Service_Drive_DriveFile();
$file->setName($documento);
//obtenemos el mime type
$finfo = finfo_open(FILEINFO_MIME_TYPE);
$mime_type=finfo_file($finfo, $documento);
//id de la carpeta donde hemos dado el permiso a la cuenta de servicio
$file->setParents(array($claveJSON));
$file->setDescription($descripcion);
$file->setMimeType($mime_type);
$result = $service->files->create(
$file,
array(
'data' => file_get_contents($documento),
'mimeType' => $mime_type,
'uploadType' => 'media',
)
);
echo "2.- Fichero subido a Google Drive.
";
}catch(Google_Service_Exception $gs){
$m=json_decode($gs->getMessage());
echo $m->error->message;
}catch(Exception $e){
echo $e->getMessage();
}
}
Diseñamos nuestro formulario HTML
<html>
<head>
<title>Subir ficheros a Google drive.</title>
</head>
<body>
<form method="POST" action="<?php echo htmlspecialchars($_SERVER["PHP_SELF"]);?>" enctype="multipart/form-data">
<label for="documento">Documento:</label>
<input type="file" name="documento" required /><br>
<label for="descripcion">Descripción:</label>
<input type="text" name="descripcion" required /><br>
<input type="submit" name="enviar" value="Subir documento a Google Drive" />
</form>
</body>
</html>
Procedemos a subir nuestro fichero a nuestro servidor de manera temporal, ya que una vez subido a Google Drive, vamos a eliminarlo.
if($_SERVER["REQUEST_METHOD"] == "POST"){
$documento = htmlspecialchars($_FILES['documento']['name']);
$descripcion = htmlspecialchars($_POST['descripcion']);
// Subimos el documento a nuestro servidor.
if(move_uploaded_file($_FILES['documento']['tmp_name'], $documento)){
echo "1.- Fichero subido al servidor.
";
subirDocumentoDrive($documento,$descripcion);
if (unlink($documento)){
echo "3.- Fichero eliminado del servidor";
}else{
echo 'Error: No se ha podido eliminar el documento "'.$documento.'" en el servidor.';
}
}else{
echo "Error: Se ha producido un error, intentelo de nuevo.";
}
}
Archivo PHP (completo)
<?php
include_once 'google-api-php-client-v2.7.2-PHP7.4/vendor/autoload.php';
function subirDocumentoDrive($documento,$descripcion){
// Variables de credenciales.
$claveJSON = '1qKTBAOXqB3d90OSubbp6Nvh10CQdFpXb';
$pathJSON = 'lacodigoteca-87cea347411f.json';
//configurar variable de entorno
putenv('GOOGLE_APPLICATION_CREDENTIALS='.$pathJSON);
$client = new Google_Client();
$client->useApplicationDefaultCredentials();
$client->setScopes(['https://www.googleapis.com/auth/drive.file']);
try{
//instanciamos el servicio
$service = new Google_Service_Drive($client);
//instacia de archivo
$file = new Google_Service_Drive_DriveFile();
$file->setName($documento);
//obtenemos el mime type
$finfo = finfo_open(FILEINFO_MIME_TYPE);
$mime_type=finfo_file($finfo, $documento);
//id de la carpeta donde hemos dado el permiso a la cuenta de servicio
$file->setParents(array($claveJSON));
$file->setDescription($descripcion);
$file->setMimeType($mime_type);
$result = $service->files->create(
$file,
array(
'data' => file_get_contents($documento),
'mimeType' => $mime_type,
'uploadType' => 'media',
)
);
/* FICHERO SUBIDO A GOOGLE DRIVE */
echo "2.- Fichero subido a Google Drive.
";
}catch(Google_Service_Exception $gs){
$m=json_decode($gs->getMessage());
echo $m->error->message;
}catch(Exception $e){
echo $e->getMessage();
}
}
if($_SERVER["REQUEST_METHOD"] == "POST"){
$documento = htmlspecialchars($_FILES['documento']['name']);
$descripcion = htmlspecialchars($_POST['descripcion']);
// Subimos el documento a nuestro servidor.
if(move_uploaded_file($_FILES['documento']['tmp_name'], $documento)){
echo "1.- Fichero subido al servidor.
";
subirDocumentoDrive($documento,$descripcion);
if (unlink($documento)){
echo "3.- Fichero eliminado del servidor";
}else{
echo 'Error: No se ha podido eliminar el documento "'.$documento.'" en el servidor.';
}
}else{
echo "Error: Se ha producido un error, intentelo de nuevo.";
}
}
?>
<html>
<head>
<title>Subir ficheros a Google drive.</title>
</head>
<body>
<form method="POST" action="<?php echo htmlspecialchars($_SERVER["PHP_SELF"]);?>" enctype="multipart/form-data">
<label for="documento">Documento:</label>
<input type="file" name="documento" required /><br>
<label for="descripcion">Descripción:</label>
<input type="text" name="descripcion" required /><br>
<input type="submit" name="enviar" value="Subir documento a Google Drive" />
</form>
</body>
</html>
Nuevo: Renovar token automáticamente de Google Drive
Creamos un archivo que se llame auth.php
con la función getAccessToken()
para obtener el token actualizado:
<?php
require_once __DIR__ . '/vendor/autoload.php';
function getAccessToken() {
$client = new Google_Client();
$client->setAuthConfig('credentials.json');
$client->addScope(Google_Service_Drive::DRIVE);
$accessToken = json_decode(file_get_contents('access_token.json'), true);
$client->setAccessToken($accessToken);
if ($client->isAccessTokenExpired()) {
$client->fetchAccessTokenWithRefreshToken($client->getRefreshToken());
file_put_contents('access_token.json', json_encode($client->getAccessToken()));
$accessToken = $client->getAccessToken();
}
return $accessToken['access_token'];
}
Después creamos una función checkAccessToken()
que compruebe si el token actualizado existe y si no, obtenga uno nuevo utilizando la función getAccessToken()
:
function checkAccessToken() {
if (file_exists('access_token.json')) {
$accessToken = json_decode(file_get_contents('access_token.json'), true);
if (!$accessToken || !isset($accessToken['access_token'])) {
$accessToken = getAccessToken();
}
} else {
$accessToken = getAccessToken();
}
return $accessToken['access_token'];
}
Utilizaremos la función checkAccessToken()
en el código donde se utiliza la API de Google Drive:
<?php
require_once __DIR__ . '/vendor/autoload.php';
$client = new Google_Client();
$client->setAuthConfig('credentials.json');
$client->setAccessToken(checkAccessToken());
$service = new Google_Service_Drive($client);
// Ejemplo de uso de la API de Google Drive
$files = $service->files->listFiles(array('pageSize' => 10));
foreach ($files->getFiles() as $file) {
echo $file->getName();
}
Nota: Si queréis subir varios documentos a Google Drive con PHP a la vez, os recomiendo que echéis un vistazo al siguiente post:
22 comentarios en “Subir documentos a Google Drive con PHP”
Hola, quiero agradecer el articulo.
Y felicitarte por lo didáctico.
Que estés muy bien! Saludos.
Hola Jorge,
Muchísimas gracias por entrar en mi blog y, ¡es de agradecer tu valoración sobre el trabajo que conlleva este tipo de artículos!
Un saludo!
Hola buenas tardes..Mira me saca error:
Fatal error: Uncaught Error: Class ‘Google\Client’ not found in D:\xampp\htdocs\UpdateDocumentsGoogleDrive\updateFilesGdrive.php:37 Stack trace: #0 D:\xampp\htdocs\UpdateDocumentsGoogleDrive\updateFilesGdrive.php(11): subirDocumentoDrive(‘Captura_req_red…’, ‘Prueba-7’) #1 {main} thrown in D:\xampp\htdocs\UpdateDocumentsGoogleDrive\updateFilesGdrive.php on line 37
Hola!
¿Tienes bien enlazado el autoload? Comprueba la ruta. También deberás de comprobar qué versión de PHP estás utilizando, el ejemplo se realizó con PHP 7.4.
Espero que se haya resuelto el error.
Un saludo.
Hola, muy buen articulo. ¿Hay alguna forma de conseguir el link una vez subido el archivo? Me gustaría poder guardar el link a cada documento que subo a google drive en mi base de datos. Gracias!
Hola Joaquín,
Me alegro que te sirviera el artículo. Para sacar el enlace, debes de usar la variable $result. Te dejo un breve ejemplo:
echo 'https://drive.google.com/open?id='.$result->id
Si quieres probarlo, debes de ponerlo justo debajo de la anotación:
echo "2.- Fichero subido a Google Drive.
";
Un saludo.
Buenas!
Antes que nada agradecerte el codigo ha ido perfecto! La duda que tengo es que lo utilizo en un formulario que se rellena a traves de un movil, entonces como podria redimensionar las imagenes ?
Muchas gracias
Hola Miguel,
Me alegro un montón que te sirva de ayuda mi blog 🙂 Es una pregunta ambigüa, te refieres a que, al subir la foto a Google Drive, ¿se redimensione las imágenes? Para ello puedes utilizar imagescale de PHP. Si es para mostrar esa imagen en un formulario, deberás de trabajar un CSS responsive con media queries.
Un saludo.
Buenas !
Si, voy a usar tu codigo para una aplicacion de tickets y se generan unos 200 al dia, entonces des de un dipositivo movil la calidad de las fotos son altas, hay alguna forma de que antes de subirlas a google drive les baje la resolucion? He buscando de diferentes maneras pero no logro encontrar la clave correcta
Tengo la duda de cuando tendria que redimensionarla
Eso depende de la funcionalidad que quieras llevarlo a cabo, si es para un thumbnail… para unos slider…
Este es un excelente ejemplo. Muchas gracias por tomar de tu tiempo y compartir las rutinas.
Hola, habría alguna forma de acceder a los subdirectorios del directorio compartido en Drive? Necesitaría que un usuario pudiera subir archivos a su carpeta en Drive. Gracias
Hola Felix,
Tal como está en el código no. Pero podrías crear el mismo caso pero dando permisos al usuario en lugar de realizarlo de forma genérica.
Un saludo.
Hola como hago para renovar automaticamente el token que despues de cierta cantidad de subida de archivos se llena las cuotas y acceso al token. Si me puedes compartir el codigo o donde tener una guia te lo agradezco
Hola Sandor. He modificado el artículo incluyendo un ejemplo.
Espero que te sirva de ayuda.
Un saludo.
Hola, ya hice todo pero me salen 2 errores en el $file = new Google_Service_DriveFile() y en el $service = new Google_Service_Drive($client);
Los 2 errores son en el Google_service
Hola Fernando,
Comprueba que tienes la librería de Google Drive en la raíz de tu fichero o donde lo tengas apuntando la librería en el include_once.
Comprueba también qué versión de PHP tienes, ya que este ejemplo está basado en la 7.4.
Un saludo.
Buen día excelente, me sirvió mucho, compré espacio en Google One pero subo y subo cosas y no consume el espacio y la cuenta de servicio se llena a las 15 gigas, me toca borrar la cuenta se servicio y crear otra; como hago para que consuma el espacio de mi cuenta, es que como si archivo que se sube fuera compartido de la cuenta de servicio a la mia y no queda realmente en cuenta.
No se como darte una posible solución, revise que los datos son correctos y a la hora de crear la aplicación que esté apuntando a la cuenta que tiene los GB contratados.
Hola, me he perdido un poco en la parte de la generación de los tokens.
Que datos deberían tener los archivos access_token.json y credentials.json ya que no lo dice por ningún lado.
Perdona si mi pregunta raya en lo obvio, pero no logro hacer funcionar esa última parte
Hola Eduardo,
Disculpa por la tardanza. He revisado tu comentario y los ficheros. Tanto acces_token.json ($claveJSON) como credentials.json ($pathJSON) deberás de invocarlo desde el fichero PHP que permite subir ficheros a Google drive.
Un saludo.