Pular para conteúdo

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:

  1. Armazenar documentos: Upload automático de contratos, PDFs, imagens
  2. Compartilhar arquivos: Gerar links compartilháveis automaticamente
  3. Organizar pastas: Criar estrutura de pastas dinamicamente
  4. Backup automatizado: Salvar cópias de arquivos importantes
  5. Integração universal: Drive é acessível de qualquer dispositivo

Como funciona internamente?

Quando o GOOGLE_DRIVE é executado, o sistema:

  1. Autentica via OAuth2 com Google (access_token e refresh_token)
  2. Conecta à API do Google Drive v3
  3. Executa operação solicitada (upload, download, list, delete, createFolder)
  4. Processa arquivos em base64 quando necessário
  5. Retorna IDs, links e metadados dos arquivos
  6. 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

  1. Upload de documentos: "Salvar contrato assinado no Drive"
  2. Backup de mídias: "Fazer backup de fotos recebidas"
  3. Compartilhar arquivos: "Gerar link de download do relatório"
  4. Organizar arquivos: "Criar pasta por cliente automaticamente"
  5. Download de templates: "Buscar template de contrato"
  6. 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
.pdf 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

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