GOOGLE_DRIVE - Integração com Google Drive
O que é este Node?
O GOOGLE_DRIVE é o node responsável por gerenciar arquivos e pastas no Google Drive, permitindo upload, download, listagem, criação de pastas e exclusão de arquivos de forma automatizada.
Por que este Node existe?
Arquivos precisam ser armazenados e compartilhados na nuvem. O GOOGLE_DRIVE existe para:
- Armazenar documentos: Upload automático de contratos, PDFs, imagens
- Compartilhar arquivos: Gerar links compartilháveis automaticamente
- Organizar pastas: Criar estrutura de pastas dinamicamente
- Backup automatizado: Salvar cópias de arquivos importantes
- Integração universal: Drive é acessível de qualquer dispositivo
Como funciona internamente?
Quando o GOOGLE_DRIVE é executado, o sistema:
- Autentica via OAuth2 com Google (access_token e refresh_token)
- Conecta à API do Google Drive v3
- Executa operação solicitada (upload, download, list, delete, createFolder)
- Processa arquivos em base64 quando necessário
- Retorna IDs, links e metadados dos arquivos
- Se erro: Retorna mensagem de erro detalhada
Código interno (google-executors.service.ts:565-663):
async executeGoogleDrive(data: any, variables: Record<string, any>): Promise<any> {
try {
this.logger.log('📁 [GOOGLE DRIVE] Executing operation');
const oauth2Client = new OAuth2Client(
process.env.GOOGLE_CLIENT_ID,
process.env.GOOGLE_CLIENT_SECRET,
process.env.GOOGLE_REDIRECT_URI
);
oauth2Client.setCredentials({
access_token: data.accessToken,
refresh_token: data.refreshToken,
});
const drive = google.drive({ version: 'v3', auth: oauth2Client });
switch (data.operation) {
case 'upload':
const uploadResult = await drive.files.create({
requestBody: {
name: data.fileName,
parents: data.folderId ? [data.folderId] : undefined,
},
media: {
mimeType: data.mimeType,
body: Buffer.from(data.content, 'base64'),
},
fields: 'id,name,webViewLink,webContentLink',
});
return {
success: true,
fileId: uploadResult.data.id,
fileName: uploadResult.data.name,
webViewLink: uploadResult.data.webViewLink,
webContentLink: uploadResult.data.webContentLink,
};
case 'download':
const downloadResult = await drive.files.get({
fileId: data.fileId,
alt: 'media',
}, {
responseType: 'arraybuffer',
});
return {
success: true,
content: Buffer.from(downloadResult.data as ArrayBuffer).toString('base64'),
};
case 'list':
const listResult = await drive.files.list({
q: data.query || `'${data.folderId || 'root'}' in parents`,
fields: 'files(id, name, mimeType, size, modifiedTime, webViewLink)',
pageSize: data.pageSize || 100,
});
return {
success: true,
files: listResult.data.files,
};
case 'delete':
await drive.files.delete({
fileId: data.fileId,
});
return {
success: true,
message: 'File deleted successfully',
};
case 'createFolder':
const createFolderResult = await drive.files.create({
requestBody: {
name: data.folderName,
mimeType: 'application/vnd.google-apps.folder',
parents: data.parentFolderId ? [data.parentFolderId] : undefined,
},
fields: 'id,name,webViewLink',
});
return {
success: true,
folderId: createFolderResult.data.id,
folderName: createFolderResult.data.name,
webViewLink: createFolderResult.data.webViewLink,
};
default:
throw new Error(`Unknown Google Drive operation: ${data.operation}`);
}
} catch (error) {
this.logger.error('Google Drive execution error:', error);
throw error;
}
}
Quando você DEVE usar este Node?
Use GOOGLE_DRIVE sempre que precisar gerenciar arquivos na nuvem:
Casos de uso
- Upload de documentos: "Salvar contrato assinado no Drive"
- Backup de mídias: "Fazer backup de fotos recebidas"
- Compartilhar arquivos: "Gerar link de download do relatório"
- Organizar arquivos: "Criar pasta por cliente automaticamente"
- Download de templates: "Buscar template de contrato"
- Listar arquivos: "Mostrar documentos disponíveis"
Quando NÃO usar GOOGLE_DRIVE
- Arquivos temporários: Use armazenamento local/S3
- Processamento em tempo real: Drive tem latência
- Arquivos muito grandes (>5GB): Considere outras soluções
Parâmetros
| Campo | Tipo | Obrigatório | Descrição |
|---|---|---|---|
| operation | string | Sim | upload, download, list, delete, createFolder |
| fileName | string | Condicional | Nome do arquivo (para upload) |
| fileId | string | Condicional | ID do arquivo (para download/delete) |
| folderId | string | Não | ID da pasta de destino |
| folderName | string | Condicional | Nome da pasta (para createFolder) |
| content | string | Condicional | Conteúdo base64 (para upload) |
| mimeType | string | Condicional | Tipo MIME do arquivo |
| query | string | Não | Query de busca (para list) |
| pageSize | number | Não | Máximo de arquivos (padrão: 100) |
| accessToken | string | Sim | Token OAuth2 do Google |
| refreshToken | string | Sim | Refresh token OAuth2 do Google |
Operações Disponíveis
1. upload - Enviar arquivo para o Drive
O que faz: Faz upload de arquivo para o Google Drive.
Parâmetros obrigatórios: - fileName - content (base64) - mimeType - accessToken - refreshToken
Parâmetros opcionais: - folderId (pasta de destino)
2. download - Baixar arquivo do Drive
O que faz: Baixa arquivo do Drive e retorna em base64.
Parâmetros obrigatórios: - fileId - accessToken - refreshToken
3. list - Listar arquivos
O que faz: Lista arquivos de uma pasta ou busca por query.
Parâmetros obrigatórios: - accessToken - refreshToken
Parâmetros opcionais: - folderId (lista arquivos da pasta) - query (busca personalizada) - pageSize (limite de resultados)
4. delete - Excluir arquivo
O que faz: Remove arquivo permanentemente do Drive.
Parâmetros obrigatórios: - fileId - accessToken - refreshToken
5. createFolder - Criar pasta
O que faz: Cria nova pasta no Drive.
Parâmetros obrigatórios: - folderName - accessToken - refreshToken
Parâmetros opcionais: - parentFolderId (pasta pai)
Exemplo 1: Upload de Documento
Objetivo: Fazer upload de um PDF para o Drive.
JSON para Importar
{
"name": "Upload Documento para Google Drive",
"nodes": [
{
"id": "start_1",
"type": "start",
"position": { "x": 100, "y": 100 },
"data": { "label": "Início" }
},
{
"id": "input_1",
"type": "input",
"position": { "x": 300, "y": 100 },
"data": {
"label": "Nome do Arquivo",
"parameters": {
"message": "Qual o nome do arquivo?",
"variable": "file_name"
}
}
},
{
"id": "variable_1",
"type": "variable",
"position": { "x": 500, "y": 100 },
"data": {
"label": "Preparar Conteúdo",
"parameters": {
"operation": "set",
"name": "file_content_base64",
"value": "JVBERi0xLjQKJeLjz9MKMSAwIG9iag..."
}
}
},
{
"id": "google_drive_1",
"type": "google_drive",
"position": { "x": 700, "y": 100 },
"data": {
"label": "Upload para Drive",
"parameters": {
"operation": "upload",
"fileName": "{{file_name}}.pdf",
"content": "{{file_content_base64}}",
"mimeType": "application/pdf",
"accessToken": "{{google_access_token}}",
"refreshToken": "{{google_refresh_token}}"
}
}
},
{
"id": "message_1",
"type": "message",
"position": { "x": 900, "y": 100 },
"data": {
"label": "Confirmar Upload",
"parameters": {
"message": "✅ Arquivo enviado com sucesso!\n\n📄 Nome: {{fileName}}\n🔗 Link: {{webViewLink}}"
}
}
},
{
"id": "end_1",
"type": "end",
"position": { "x": 1100, "y": 100 },
"data": { "label": "Fim" }
}
],
"edges": [
{ "source": "start_1", "target": "input_1" },
{ "source": "input_1", "target": "variable_1" },
{ "source": "variable_1", "target": "google_drive_1" },
{ "source": "google_drive_1", "target": "message_1" },
{ "source": "message_1", "target": "end_1" }
]
}
Saída esperada:
Sistema: Qual o nome do arquivo?
Usuário: Contrato-2025
Sistema: ✅ Arquivo enviado com sucesso!
📄 Nome: Contrato-2025.pdf
🔗 Link: https://drive.google.com/file/d/1ABC123.../view
Exemplo 2: Criar Pasta e Upload
Objetivo: Criar pasta para cliente e fazer upload de documento.
JSON para Importar
{
"name": "Criar Pasta Cliente e Upload",
"nodes": [
{
"id": "start_1",
"type": "start",
"position": { "x": 100, "y": 100 },
"data": { "label": "Início" }
},
{
"id": "input_1",
"type": "input",
"position": { "x": 300, "y": 100 },
"data": {
"label": "Nome do Cliente",
"parameters": {
"message": "Nome do cliente:",
"variable": "cliente_nome"
}
}
},
{
"id": "google_drive_1",
"type": "google_drive",
"position": { "x": 500, "y": 100 },
"data": {
"label": "Criar Pasta Cliente",
"parameters": {
"operation": "createFolder",
"folderName": "Cliente - {{cliente_nome}}",
"accessToken": "{{google_access_token}}",
"refreshToken": "{{google_refresh_token}}"
}
}
},
{
"id": "message_1",
"type": "message",
"position": { "x": 700, "y": 100 },
"data": {
"label": "Pasta Criada",
"parameters": {
"message": "✅ Pasta criada!\n\n📁 {{folderName}}\n🔗 {{webViewLink}}"
}
}
},
{
"id": "google_drive_2",
"type": "google_drive",
"position": { "x": 900, "y": 100 },
"data": {
"label": "Upload Documento",
"parameters": {
"operation": "upload",
"fileName": "Contrato-{{cliente_nome}}.pdf",
"content": "{{documento_base64}}",
"mimeType": "application/pdf",
"folderId": "{{folderId}}",
"accessToken": "{{google_access_token}}",
"refreshToken": "{{google_refresh_token}}"
}
}
},
{
"id": "message_2",
"type": "message",
"position": { "x": 1100, "y": 100 },
"data": {
"label": "Documento Enviado",
"parameters": {
"message": "📄 Documento salvo na pasta do cliente!"
}
}
},
{
"id": "end_1",
"type": "end",
"position": { "x": 1300, "y": 100 },
"data": { "label": "Fim" }
}
],
"edges": [
{ "source": "start_1", "target": "input_1" },
{ "source": "input_1", "target": "google_drive_1" },
{ "source": "google_drive_1", "target": "message_1" },
{ "source": "message_1", "target": "google_drive_2" },
{ "source": "google_drive_2", "target": "message_2" },
{ "source": "message_2", "target": "end_1" }
]
}
Exemplo 3: Listar Arquivos e Download
Objetivo: Listar arquivos disponíveis e permitir download.
JSON para Importar
{
"name": "Listar e Baixar Arquivos do Drive",
"nodes": [
{
"id": "start_1",
"type": "start",
"position": { "x": 100, "y": 100 },
"data": { "label": "Início" }
},
{
"id": "google_drive_1",
"type": "google_drive",
"position": { "x": 300, "y": 100 },
"data": {
"label": "Listar Arquivos",
"parameters": {
"operation": "list",
"pageSize": 10,
"accessToken": "{{google_access_token}}",
"refreshToken": "{{google_refresh_token}}"
}
}
},
{
"id": "message_1",
"type": "message",
"position": { "x": 500, "y": 100 },
"data": {
"label": "Mostrar Lista",
"parameters": {
"message": "📂 Seus arquivos no Drive:\n\n(Lista de arquivos aqui)"
}
}
},
{
"id": "input_1",
"type": "input",
"position": { "x": 700, "y": 100 },
"data": {
"label": "Escolher Arquivo",
"parameters": {
"message": "Digite o ID do arquivo para baixar:",
"variable": "file_id"
}
}
},
{
"id": "google_drive_2",
"type": "google_drive",
"position": { "x": 900, "y": 100 },
"data": {
"label": "Download Arquivo",
"parameters": {
"operation": "download",
"fileId": "{{file_id}}",
"accessToken": "{{google_access_token}}",
"refreshToken": "{{google_refresh_token}}"
}
}
},
{
"id": "message_2",
"type": "message",
"position": { "x": 1100, "y": 100 },
"data": {
"label": "Arquivo Baixado",
"parameters": {
"message": "✅ Arquivo baixado com sucesso!"
}
}
},
{
"id": "end_1",
"type": "end",
"position": { "x": 1300, "y": 100 },
"data": { "label": "Fim" }
}
],
"edges": [
{ "source": "start_1", "target": "google_drive_1" },
{ "source": "google_drive_1", "target": "message_1" },
{ "source": "message_1", "target": "input_1" },
{ "source": "input_1", "target": "google_drive_2" },
{ "source": "google_drive_2", "target": "message_2" },
{ "source": "message_2", "target": "end_1" }
]
}
Resposta do Node
Operação upload
{
"success": true,
"fileId": "1ABC123XYZ...",
"fileName": "Contrato-2025.pdf",
"webViewLink": "https://drive.google.com/file/d/1ABC123.../view",
"webContentLink": "https://drive.google.com/uc?id=1ABC123..."
}
Operação download
{
"success": true,
"content": "JVBERi0xLjQKJeLjz9MKMSAwIG9iag..."
}
Operação list
{
"success": true,
"files": [
{
"id": "1ABC123...",
"name": "Contrato.pdf",
"mimeType": "application/pdf",
"size": "256789",
"modifiedTime": "2025-01-15T10:30:00.000Z",
"webViewLink": "https://drive.google.com/file/d/..."
}
]
}
Operação createFolder
{
"success": true,
"folderId": "1FOLDER123...",
"folderName": "Cliente - João Silva",
"webViewLink": "https://drive.google.com/drive/folders/1FOLDER123..."
}
Operação delete
{
"success": true,
"message": "File deleted successfully"
}
Tipos MIME Comuns
| Extensão | MIME Type |
|---|---|
| application/pdf | |
| .doc | application/msword |
| .docx | application/vnd.openxmlformats-officedocument.wordprocessingml.document |
| .xls | application/vnd.ms-excel |
| .xlsx | application/vnd.openxmlformats-officedocument.spreadsheetml.sheet |
| .jpg | image/jpeg |
| .png | image/png |
| .txt | text/plain |
| .zip | application/zip |
Como obter fileId e folderId
Os IDs estão na URL do Google Drive:
Arquivo:
https://drive.google.com/file/d/1ABC123XYZ.../view
^^^^^^^^^^
fileId
Pasta:
https://drive.google.com/drive/folders/1FOLDER123...
^^^^^^^^^^^
folderId
Query de Busca (Search)
Exemplos de queries para o parâmetro query na operação list:
name = 'Contrato.pdf'
mimeType = 'application/pdf'
name contains 'Contrato'
modifiedTime > '2025-01-01T00:00:00'
'1FOLDER123...' in parents
trashed = false
Documentação completa: Google Drive Search Query
Conversão Base64
Para enviar arquivos, converta para base64:
// Node.js
const fs = require('fs');
const fileContent = fs.readFileSync('arquivo.pdf');
const base64 = fileContent.toString('base64');
# Python
import base64
with open('arquivo.pdf', 'rb') as f:
base64_content = base64.b64encode(f.read()).decode('utf-8')
Boas Práticas
✅ SIM:
- Organize arquivos em pastas por cliente/projeto
- Use nomes descritivos para arquivos
- Verifique mimeType correto antes do upload
- Armazene fileIds para referência futura
- Use webViewLink para compartilhar com usuários
❌ NÃO:
- Não faça upload de arquivos muito grandes sem aviso
- Não delete arquivos sem confirmação
- Não exponha tokens em logs
- Não faça múltiplos uploads simultâneos (rate limit)
- Não armazene senhas em arquivos não criptografados
Dicas
💡 Organização: Crie estrutura de pastas consistente desde o início
💡 Compartilhamento: webViewLink permite visualizar, webContentLink permite download direto
💡 Backup: Faça backup de fileIds importantes no banco de dados
💡 Permissões: Configure permissões de compartilhamento via API se necessário
💡 Tamanho limite: API suporta até 5TB por arquivo (mas considere performance)
Troubleshooting
Erro: "File not found"
Causa: fileId inválido ou arquivo deletado
Solução: Verifique o ID na URL do arquivo ou use list para buscar
Erro: "Insufficient permissions"
Causa: Token sem scope adequado
Solução: Adicione scope https://www.googleapis.com/auth/drive ou drive.file
Erro: "Invalid MIME type"
Causa: mimeType não corresponde ao conteúdo
Solução: Verifique tabela de MIME types e use o correto
Erro: "Quota exceeded"
Causa: Limite de armazenamento do Drive atingido
Solução: Libere espaço ou aumente cota do Google Workspace
Próximo Node
→ GOOGLE_SHEETS - Integrar com Google Sheets → GOOGLE_DOCS - Manipular documentos do Google → GOOGLE_CALENDAR - Gerenciar eventos no Calendar