Com meu curso de Node.js e MongoDB chegando aos quase 200 inscritos na data em que escrevo este tutorial, muitas ideias tem me sido enviadas com relação a temas para posts e novas aulas no curso. Recentemente, um aluno estava tentando fazer algo que me chamou a atenção: uma API em Node.js que recebesse um arquivo e o enviasse para o Google Drive.
Assim, no artigo de hoje quero mostrar como você pode criar uma integração do Node.js com o Google Drive facilmente. Vamos enviar imagens, mas você pode facilmente adaptar o código para enviar outro tipo de arquivo.
Vamos lá!
Google Drive
Obviamente para que você consiga acompanhar este tutorial você deve ter uma conta no Google Drive. Se você possui um Gmail, automaticamente possui uma pois seus emails são armazenados na mesma que, em seu nível gratuito, fornece 15GB de armazenamento na nuvem. Por cerca de R$70/ano você faz um upgrade para 100GB o que lhe permite salvar muita coisa de maneira rápida e segura.
Caso não possua uma, crie em drive.google.com
Surpreendentemente, existe todo um suporte do Google à tecnologia Node.js, que você confere neste painel do Google Drive APIs. Acesse o painel e clique no botão “Enable Drive API” para que seja possível se integrar com a sua conta do GDrive, conforme a imagem abaixo.
Ao ativar a API, você receberá um Client ID e um Client Secret, que serão necessários para a autenticação na aplicação Node.js. Guarde-os consigo, pois eu não vou fornecer os meus, hehehe. Também lhe é oferecido um arquivo de credenciais (credentials.json), baixe e salve-o na pasta do projeto que vamos criar a seguir.
Criando o projeto em Node
Crie uma pasta na sua máquina chamada gdrive-node e navegue até ela via terminal. Crie um gdrive-auth.js vazio e rode um ‘npm init’ para criar uma aplicação. Depois instale a biblioteca do GDrive usando o comando abaixo:
1 2 3 |
npm install googleapis@latest --save |
Lembre-se de ter o seu arquivo credentials.json dentro da pasta do projeto, pois agora vamos carregá-lo na nossa aplicação. Abra o gdrive-auth.js e inclua o seguinte código, adaptado da documentação do Google Drive APIs:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 |
//index.js const fs = require('fs'); const readline = require('readline'); const {google} = require('googleapis'); // If modifying these scopes, delete token.json. const SCOPES = ['https://www.googleapis.com/auth/drive.metadata.readonly']; // The file token.json stores the user's access and refresh tokens, and is // created automatically when the authorization flow completes for the first // time. const TOKEN_PATH = 'token.json'; function callGDriveApi(callback){ // Load client secrets from a local file. fs.readFile('credentials.json', (err, content) => { if (err) return console.log('Error loading client secret file:', err); // Authorize a client with credentials, then call the Google Drive API. if(callback) authorize(JSON.parse(content), callback); else authorize(JSON.parse(content), listFiles);//default }); } /** * Create an OAuth2 client with the given credentials, and then execute the * given callback function. * @param {Object} credentials The authorization client credentials. * @param {function} callback The callback to call with the authorized client. */ function authorize(credentials, callback) { const {client_secret, client_id, redirect_uris} = credentials.installed; const oAuth2Client = new google.auth.OAuth2( client_id, client_secret, redirect_uris[0]); // Check if we have previously stored a token. fs.readFile(TOKEN_PATH, (err, token) => { if (err) return getAccessToken(oAuth2Client, callback); oAuth2Client.setCredentials(JSON.parse(token)); callback(oAuth2Client); }); } /** * Get and store new token after prompting for user authorization, and then * execute the given callback with the authorized OAuth2 client. * @param {google.auth.OAuth2} oAuth2Client The OAuth2 client to get token for. * @param {getEventsCallback} callback The callback for the authorized client. */ function getAccessToken(oAuth2Client, callback) { const authUrl = oAuth2Client.generateAuthUrl({ access_type: 'offline', scope: SCOPES, }); console.log('Authorize this app by visiting this url:', authUrl); const rl = readline.createInterface({ input: process.stdin, output: process.stdout, }); rl.question('Enter the code from that page here: ', (code) => { rl.close(); oAuth2Client.getToken(code, (err, token) => { if (err) return console.error('Error retrieving access token', err); oAuth2Client.setCredentials(token); // Store the token to disk for later program executions fs.writeFile(TOKEN_PATH, JSON.stringify(token), (err) => { if (err) return console.error(err); console.log('Token stored to', TOKEN_PATH); }); callback(oAuth2Client); }); }); } /** * Lists the names and IDs of up to 10 files. * @param {google.auth.OAuth2} auth An authorized OAuth2 client. */ function listFiles(auth) { const drive = google.drive({version: 'v3', auth}); drive.files.list({ pageSize: 10, fields: 'nextPageToken, files(id, name)', }, (err, res) => { if (err) return console.log('The API returned an error: ' + err); const files = res.data.files; if (files.length) { console.log('Files:'); files.map((file) => { console.log(`${file.name} (${file.id})`); }); } else { console.log('No files found.'); } }); } callGDriveApi(); module.exports = callGDriveApi; |
Basicamente o que temos aqui é o código que implementa a autenticação OAuth offline. Ou seja, a sua aplicação vai solicitar um token para a sua conta do Google Drive, que vai ser utilizada pela sua aplicação. Mais tarde usaremos este módulo para chamar a API do GDrive.
Ao executar esse código pela primeira vez no console (node gdrive-auth) você receberá uma URL que deve ser acessada. Copie a URL e ao acessar a página no navegador, você verá a sua conta do Google e ela vai lhe questionar se você quer conceder acesso à essa aplicação Node (Quickstart). Fornecendo a permissão você receberá o token que deve ser informado no terminal novamente, para que seja gravado.
Se tudo ocorrer bem, um teste deve ser realizado automaticamente listando os 10 últimos arquivos adicionados na sua conta do GDrive. Com isso temos um projeto configurado e autenticado para acessar as APIs do Google Drive (essa autenticação é feita apenas uma vez, para obter o arquivo token.json, que fica na raiz da sua aplicação).
Atenção: o escopo da permissão que solicitamos é para gerenciar pastas e arquivos enviados pela própria aplicação. Sendo assim, no primeiro teste não será listado nenhum arquivo pois a aplicação não criou nada ainda. Nos testes subsequentes, no console serão listados os arquivos que já fizemos upload.
Se precisar mudar o escopo de permissão (na variável SCOPES), certifique-se também de excluir o arquivo token.json para que o processo de autenticação reinicie corretamente e ele seja criado com as permissões corretas.
Enviando uma imagem
Agora vamos criar outro módulo no nosso projeto, em um arquivo gdrive.js, com o seguinte conteúdo, adaptado também da documentação oficial:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 |
const fs = require("fs"); const {google} = require('googleapis'); function imageUpload(fileName, filePath, callback){ require("./gdrive-auth")((auth) => { const fileMetadata = { name: fileName }; const media = { mimeType: "image/jpeg", body: fs.createReadStream(filePath) } const drive = google.drive({version: 'v3', auth}); drive.files.create({ resource: fileMetadata, media: media, fields: 'id' }, function (err, file) { if (err) { // Handle error console.error(err); } else { callback(file.data.id); } }); }); } module.exports = { imageUpload }; |
Neste módulo nós usamos o módulo anterior, de autenticação, e depois enviamos uma imagem passada como argumento para o GDrive criar ela idêntica na nuvem. O argumento fileName é apenas o nome da imagem enquanto que o filePath é o caminho relativo ou literal. Após a criação, será executado um callback com o ID do arquivo no GDrive que acabamos de criar.
Caso queira fazer upload de outros arquivos que não sejam imagens JPG, basta trocar o mime-type.
Agora que temos um módulo de autenticação e um de upload de imagem, vamos criar um index.js para realizar alguns testes:
1 2 3 4 5 6 7 |
//index.js const gdrive = require("./gdrive"); gdrive.imageUpload("imagem.jpg", "./imagem.jpg", (id) => { console.log(id); }); |
Aqui estou considerando que você tem um arquivo chamado imagem.jpg dentro da pasta do projeto, no mesmo nível dos módulos. Rode essa aplicação com “node index” e você deve encontrar o novo arquivo na sua conta do GDrive, na raiz do mesmo.
Agora, com as adaptações certas, você pode usar esse módulo em uma web API Express ou mesmo com algum outro framework do Node, para compor uma solução de verdade.
Espero que tenha gostado!
A parte 2 deste tutorial pode ser lida neste post.
Curtiu o tutorial? Para mais conteúdos bacanas em texto e videoaulas, conheça o meu curso de Node.js e MongoDB clicando no banner abaixo.
Olá, tudo bem?
O que você achou deste conteúdo? Conte nos comentários.
Exatamente o que estou precisando fazer. Receber arquivos no backend e enviar para o Drive.
Muito bom o seu curso de Node e Mongo DB. Já fui seu aluno e retornarei em breve
Será um prazer tê-lo novamente como aluno Airton!