FTP_UPLOAD - Enviar Arquivo para Servidor FTP
O que é este Node?
O FTP_UPLOAD é o node responsável por enviar arquivos do sistema local para um servidor FTP remoto. Faz parte do conjunto de operações FTP para transferência de arquivos.
Por que este Node existe?
Transferir arquivos para servidores remotos é uma necessidade comum em automações empresariais. O FTP_UPLOAD existe para:
- Distribuir Documentos: Enviar relatórios, contratos e documentos gerados para servidores de parceiros
- Publicar Arquivos: Fazer upload de imagens, vídeos e assets para servidores de hospedagem
- Backup Automatizado: Enviar backups de dados para servidores FTP externos
- Integração B2B: Trocar arquivos com parceiros que usam FTP como canal de integração
Como funciona internamente?
Quando o FTP_UPLOAD é executado, o sistema:
- Valida Arquivo Local: Verifica se o arquivo especificado existe no sistema
- Conecta ao FTP: Estabelece conexão com servidor usando credenciais fornecidas
- Prepara Transfer: Cria streams de leitura do arquivo local
- Envia Arquivo: Transfere bytes do arquivo local para caminho remoto especificado
- Registra Tamanho: Captura tamanho do arquivo enviado para confirmação
- Se falhar: Retorna erro detalhando problema (arquivo não encontrado, sem permissão, etc)
- Se sucesso: Confirma upload com timestamp e detalhes do arquivo
Código interno (ftp-executor.service.ts:284-304):
private async uploadFile(client: FTP.Client, data: FTPNodeData): Promise<any> {
const localPath = data.localFilePath!;
const remotePath = data.remoteFilePath!;
// Check if local file exists
if (!fs.existsSync(localPath)) {
throw new Error(`Local file not found: ${localPath}`);
}
this.logger.debug(`Uploading file: ${localPath} → ${remotePath}`);
await client.uploadFrom(localPath, remotePath);
return {
success: true,
localPath,
remotePath,
size: fs.statSync(localPath).size,
uploadedAt: new Date().toISOString()
};
}
Quando você DEVE usar este Node?
Use FTP_UPLOAD sempre que precisar de enviar arquivos para servidor FTP remoto:
Casos de uso
- Relatórios Diários: "Enviar relatório de vendas gerado às 18h para servidor FTP do cliente"
- Upload de Mídias: "Fazer upload de imagens de produtos para servidor de e-commerce via FTP"
- Backup de Dados: "Enviar backup do banco de dados para servidor FTP externo todas as noites"
Quando NÃO usar FTP_UPLOAD
- APIs Disponíveis: Use endpoints REST se a aplicação oferecer API moderna
- Cloud Storage: Use nodes S3, Google Drive ou Dropbox para armazenamento em nuvem
- Transferências Seguras: Use SFTP_UPLOAD para dados sensíveis (mais seguro que FTP)
Parâmetros Detalhados
localFilePath (string, obrigatório)
O que é: Caminho completo do arquivo no sistema local que será enviado.
Padrão: Nenhum (obrigatório)
Flow completo para testar:
{
"name": "Teste FTP Upload - LocalPath",
"nodes": [
{
"id": "start_1",
"type": "start",
"position": { "x": 100, "y": 100 },
"data": { "label": "Início" }
},
{
"id": "variable_1",
"type": "variable",
"position": { "x": 300, "y": 100 },
"data": {
"label": "Definir Arquivo Local",
"parameters": {
"variableName": "local_file",
"value": "/tmp/relatorio_vendas.pdf"
}
}
},
{
"id": "ftp_1",
"type": "ftp",
"position": { "x": 500, "y": 100 },
"data": {
"label": "Upload Arquivo",
"parameters": {
"host": "ftp.example.com",
"username": "user",
"password": "pass123",
"operation": "upload",
"localFilePath": "{{local_file}}",
"remoteFilePath": "/uploads/relatorio.pdf",
"outputVariable": "upload_result"
}
}
},
{
"id": "message_1",
"type": "message",
"position": { "x": 700, "y": 100 },
"data": {
"label": "Confirmar",
"parameters": {
"message": "Arquivo enviado: {{upload_result.size}} bytes"
}
}
},
{
"id": "end_1",
"type": "end",
"position": { "x": 900, "y": 100 },
"data": { "label": "Fim" }
}
],
"edges": [
{ "source": "start_1", "target": "variable_1" },
{ "source": "variable_1", "target": "ftp_1" },
{ "source": "ftp_1", "target": "message_1" },
{ "source": "message_1", "target": "end_1" }
]
}
Teste: O arquivo deve existir no caminho especificado antes do upload.
remoteFilePath (string, obrigatório)
O que é: Caminho completo onde o arquivo será salvo no servidor FTP remoto.
Padrão: Nenhum (obrigatório)
Flow completo para testar:
{
"name": "Teste FTP Upload - RemotePath",
"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": "Pedir Caminho Remoto",
"parameters": {
"message": "Para qual pasta enviar? (Ex: /uploads/2025/)",
"variableName": "remote_folder"
}
}
},
{
"id": "ftp_1",
"type": "ftp",
"position": { "x": 500, "y": 100 },
"data": {
"label": "Upload com Path Dinâmico",
"parameters": {
"host": "ftp.example.com",
"username": "user",
"password": "pass",
"operation": "upload",
"localFilePath": "/tmp/documento.pdf",
"remoteFilePath": "{{remote_folder}}/documento.pdf"
}
}
},
{
"id": "message_1",
"type": "message",
"position": { "x": 700, "y": 100 },
"data": {
"label": "Confirmar",
"parameters": {
"message": "Arquivo enviado para: {{remote_folder}}"
}
}
},
{
"id": "end_1",
"type": "end",
"position": { "x": 900, "y": 100 },
"data": { "label": "Fim" }
}
],
"edges": [
{ "source": "start_1", "target": "input_1" },
{ "source": "input_1", "target": "ftp_1" },
{ "source": "ftp_1", "target": "message_1" },
{ "source": "message_1", "target": "end_1" }
]
}
Teste: Digite "/uploads/2025/". Sistema enviará arquivo para esta pasta remota.
outputVariable (string, opcional)
O que é: Nome da variável onde resultado do upload será armazenado.
Padrão: "ftp_result"
Flow completo para testar:
{
"name": "Teste FTP Upload - OutputVariable",
"nodes": [
{
"id": "start_1",
"type": "start",
"position": { "x": 100, "y": 100 },
"data": { "label": "Início" }
},
{
"id": "ftp_1",
"type": "ftp",
"position": { "x": 300, "y": 100 },
"data": {
"label": "Upload com Variável Customizada",
"parameters": {
"host": "ftp.example.com",
"username": "user",
"password": "pass",
"operation": "upload",
"localFilePath": "/tmp/relatorio.pdf",
"remoteFilePath": "/reports/relatorio.pdf",
"outputVariable": "upload_details"
}
}
},
{
"id": "message_1",
"type": "message",
"position": { "x": 500, "y": 100 },
"data": {
"label": "Mostrar Detalhes",
"parameters": {
"message": "Upload concluído!\nTamanho: {{upload_details.size}} bytes\nHora: {{upload_details.uploadedAt}}"
}
}
},
{
"id": "end_1",
"type": "end",
"position": { "x": 700, "y": 100 },
"data": { "label": "Fim" }
}
],
"edges": [
{ "source": "start_1", "target": "ftp_1" },
{ "source": "ftp_1", "target": "message_1" },
{ "source": "message_1", "target": "end_1" }
]
}
Teste: Resultado fica disponível em {{upload_details}} para usar em nodes posteriores.
Parâmetros
| Campo | Tipo | Obrigatório | Descrição |
|---|---|---|---|
| host | string | Sim | Endereço do servidor FTP |
| port | number | Não | Porta TCP (padrão: 21) |
| username | string | Sim | Nome de usuário |
| password | string | Sim | Senha |
| secure | boolean | Não | FTPS - SSL/TLS (padrão: false) |
| operation | string | Sim | Deve ser "upload" |
| localFilePath | string | Sim | Caminho do arquivo local a enviar |
| remoteFilePath | string | Sim | Caminho destino no servidor remoto |
| outputVariable | string | Não | Variável de resultado (padrão: ftp_result) |
Exemplo 1: Upload de Relatório Diário Automatizado
Objetivo: Enviar relatório PDF gerado automaticamente para servidor FTP do cliente
JSON para Importar
{
"name": "Upload Relatório Diário",
"nodes": [
{
"id": "start_1",
"type": "start",
"position": { "x": 100, "y": 100 },
"data": { "label": "Início (18h diariamente)" }
},
{
"id": "variable_1",
"type": "variable",
"position": { "x": 300, "y": 100 },
"data": {
"label": "Preparar Caminhos",
"parameters": {
"variableName": "data_hoje",
"value": "2025-01-15"
}
}
},
{
"id": "ftp_1",
"type": "ftp",
"position": { "x": 500, "y": 100 },
"data": {
"label": "Upload Relatório",
"parameters": {
"host": "ftp.cliente.com",
"port": 21,
"username": "empresa_reports",
"password": "secret123",
"secure": false,
"operation": "upload",
"localFilePath": "/var/reports/vendas_{{data_hoje}}.pdf",
"remoteFilePath": "/incoming/vendas_{{data_hoje}}.pdf",
"outputVariable": "upload_info"
}
}
},
{
"id": "message_1",
"type": "message",
"position": { "x": 700, "y": 100 },
"data": {
"label": "Notificar Sucesso",
"parameters": {
"message": "✅ Relatório enviado!\nTamanho: {{upload_info.size}} bytes\nData: {{data_hoje}}"
}
}
},
{
"id": "end_1",
"type": "end",
"position": { "x": 900, "y": 100 },
"data": { "label": "Fim" }
}
],
"edges": [
{ "source": "start_1", "target": "variable_1" },
{ "source": "variable_1", "target": "ftp_1" },
{ "source": "ftp_1", "target": "message_1" },
{ "source": "message_1", "target": "end_1" }
]
}
Saída esperada:
Sistema: ✅ Relatório enviado!
Tamanho: 524288 bytes
Data: 2025-01-15
Exemplo 2: Upload de Múltiplas Imagens com Confirmação
Objetivo: Enviar várias imagens de produtos para servidor FTP e confirmar cada uma
JSON para Importar
{
"name": "Upload Múltiplas Imagens",
"nodes": [
{
"id": "start_1",
"type": "start",
"position": { "x": 100, "y": 100 },
"data": { "label": "Início" }
},
{
"id": "ftp_1",
"type": "ftp",
"position": { "x": 300, "y": 100 },
"data": {
"label": "Upload Imagem 1",
"parameters": {
"host": "ftp.loja.com",
"username": "produtos",
"password": "pass123",
"operation": "upload",
"localFilePath": "/tmp/produto_001.jpg",
"remoteFilePath": "/images/produtos/produto_001.jpg",
"outputVariable": "img1"
}
}
},
{
"id": "ftp_2",
"type": "ftp",
"position": { "x": 500, "y": 100 },
"data": {
"label": "Upload Imagem 2",
"parameters": {
"host": "ftp.loja.com",
"username": "produtos",
"password": "pass123",
"operation": "upload",
"localFilePath": "/tmp/produto_002.jpg",
"remoteFilePath": "/images/produtos/produto_002.jpg",
"outputVariable": "img2"
}
}
},
{
"id": "ftp_3",
"type": "ftp",
"position": { "x": 700, "y": 100 },
"data": {
"label": "Upload Imagem 3",
"parameters": {
"host": "ftp.loja.com",
"username": "produtos",
"password": "pass123",
"operation": "upload",
"localFilePath": "/tmp/produto_003.jpg",
"remoteFilePath": "/images/produtos/produto_003.jpg",
"outputVariable": "img3"
}
}
},
{
"id": "message_1",
"type": "message",
"position": { "x": 900, "y": 100 },
"data": {
"label": "Resumo Final",
"parameters": {
"message": "📤 3 imagens enviadas:\n✅ {{img1.remotePath}}\n✅ {{img2.remotePath}}\n✅ {{img3.remotePath}}"
}
}
},
{
"id": "end_1",
"type": "end",
"position": { "x": 1100, "y": 100 },
"data": { "label": "Fim" }
}
],
"edges": [
{ "source": "start_1", "target": "ftp_1" },
{ "source": "ftp_1", "target": "ftp_2" },
{ "source": "ftp_2", "target": "ftp_3" },
{ "source": "ftp_3", "target": "message_1" },
{ "source": "message_1", "target": "end_1" }
]
}
Saída esperada:
Sistema: 📤 3 imagens enviadas:
✅ /images/produtos/produto_001.jpg
✅ /images/produtos/produto_002.jpg
✅ /images/produtos/produto_003.jpg
Exemplo 3: Upload com Validação de Arquivo Local
Objetivo: Verificar existência do arquivo antes de tentar upload
JSON para Importar
{
"name": "Upload com Validação",
"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": "Pedir Caminho do Arquivo",
"parameters": {
"message": "Digite o caminho completo do arquivo:",
"variableName": "arquivo_local"
}
}
},
{
"id": "ftp_1",
"type": "ftp",
"position": { "x": 500, "y": 100 },
"data": {
"label": "Tentar Upload",
"parameters": {
"host": "ftp.backup.com",
"port": 21,
"username": "backup_user",
"password": "secure_pass",
"secure": true,
"operation": "upload",
"localFilePath": "{{arquivo_local}}",
"remoteFilePath": "/backups/{{arquivo_local}}",
"outputVariable": "resultado_upload"
}
}
},
{
"id": "message_success",
"type": "message",
"position": { "x": 700, "y": 50 },
"data": {
"label": "Sucesso",
"parameters": {
"message": "✅ Arquivo enviado com sucesso!\nTamanho: {{resultado_upload.size}} bytes"
}
}
},
{
"id": "end_1",
"type": "end",
"position": { "x": 900, "y": 100 },
"data": { "label": "Fim" }
}
],
"edges": [
{ "source": "start_1", "target": "input_1" },
{ "source": "input_1", "target": "ftp_1" },
{ "source": "ftp_1", "target": "message_success" },
{ "source": "message_success", "target": "end_1" }
]
}
Saída esperada:
Sistema: Digite o caminho completo do arquivo:
Usuário: /tmp/backup_database.sql
Sistema: ✅ Arquivo enviado com sucesso!
Tamanho: 2048576 bytes
Resposta do Node
{
"success": true,
"data": {
"ftp_result": {
"success": true,
"localPath": "/tmp/relatorio.pdf",
"remotePath": "/uploads/relatorio.pdf",
"size": 524288,
"uploadedAt": "2025-01-15T18:30:00.000Z"
},
"operation": "upload",
"host": "ftp.example.com",
"timestamp": "2025-01-15T18:30:00.000Z"
},
"executionTime": 2345,
"logs": [
"Uploaded file: /tmp/relatorio.pdf → /uploads/relatorio.pdf"
]
}
Boas Práticas
✅ SIM:
- Valide existência do arquivo local antes do upload
- Use caminhos absolutos para maior confiabilidade
- Organize arquivos remotos em pastas com estrutura lógica (ex: /uploads/2025/01/)
- Inclua data/timestamp no nome do arquivo para versionamento
- Use FTPS (secure: true) para upload de dados sensíveis
❌ NÃO:
- Não tente fazer upload de arquivos que não existem localmente
- Não use caminhos relativos que dependem do diretório de execução
- Não sobrescreva arquivos importantes sem backup
- Não faça upload de arquivos gigantes sem considerar timeout
- Não ignore erros de upload - sempre trate falhas adequadamente
Dicas
💡 Dica 1: Velocidade do upload depende da sua conexão de internet. Arquivos grandes podem levar minutos.
💡 Dica 2: Se upload falhar, verifique: (1) arquivo existe localmente, (2) você tem permissão de escrita no servidor remoto, (3) caminho remoto está correto.
💡 Dica 3: Para upload de múltiplos arquivos, considere usar node LOOP para iterar sobre lista de arquivos.
💡 Dica 4: FTP transfere arquivos em modo binário ou texto. Para PDFs, imagens e executáveis, modo binário é automático.
Próximos Nodes
→ FTP_DOWNLOAD - Baixar arquivo do servidor FTP → FTP_LIST - Listar arquivos antes de fazer upload → FTP_DELETE - Apagar arquivo antigo após upload de nova versão → FTP_MKDIR - Criar diretório antes de fazer upload