Pular para conteúdo

FTP_LIST - Listar Arquivos no Servidor FTP

O que é este Node?

O FTP_LIST é o node responsável por listar arquivos e diretórios em um servidor FTP remoto. Permite visualizar conteúdo de pastas e obter metadados dos arquivos.

Por que este Node existe?

Antes de baixar, apagar ou processar arquivos, é necessário saber o que existe no servidor. O FTP_LIST existe para:

  1. Descobrir Arquivos: Verificar quais arquivos estão disponíveis em um diretório remoto
  2. Obter Metadados: Conhecer tamanho, data de modificação e permissões dos arquivos
  3. Validar Existência: Confirmar se arquivo esperado foi depositado no servidor
  4. Processar em Lote: Listar múltiplos arquivos para processar em loop

Como funciona internamente?

Quando o FTP_LIST é executado, o sistema:

  1. Conecta ao FTP: Estabelece conexão com servidor usando credenciais
  2. Navega para Diretório: Acessa o caminho remoto especificado
  3. Lista Conteúdo: Executa comando LIST no servidor FTP
  4. Processa Resposta: Parseia resposta do servidor para extrair metadados
  5. Filtra Informações: Extrai nome, tipo, tamanho, data, permissões, etc
  6. Se falhar: Retorna erro (diretório não existe, sem permissão, etc)
  7. Se sucesso: Retorna array com detalhes de cada arquivo/diretório

Código interno (ftp-executor.service.ts:329-355):

private async listFiles(client: FTP.Client, data: FTPNodeData): Promise<any> {
  const remotePath = data.remotePath || '/';

  this.logger.debug(`Listing files in: ${remotePath}`);

  const files = await client.list(remotePath);

  const fileList = files.map(file => ({
    name: file.name,
    type: file.type === 1 ? 'file' : file.type === 2 ? 'directory' : 'unknown',
    size: file.size,
    modifiedAt: file.modifiedAt,
    permissions: file.permissions,
    user: file.user,
    group: file.group,
    isDirectory: file.isDirectory,
    isFile: file.isFile,
    isSymbolicLink: file.isSymbolicLink
  }));

  return {
    success: true,
    path: remotePath,
    files: fileList,
    count: fileList.length
  };
}

Quando você DEVE usar este Node?

Use FTP_LIST sempre que precisar de visualizar conteúdo de diretório FTP:

Casos de uso

  1. Buscar Arquivos Novos: "Listar diretório /incoming/ para ver se fornecedor depositou novos pedidos"
  2. Validar Upload: "Verificar se arquivo foi realmente enviado após upload"
  3. Processar Lote: "Listar todos os XMLs em /invoices/ para processar um por um"

Quando NÃO usar FTP_LIST

  • Arquivo Específico: Se sabe nome exato, baixe direto com FTP_DOWNLOAD
  • Verificar Existência: Use SFTP_EXISTS (SFTP) para checar arquivo específico
  • Árvore Completa: FTP_LIST lista um diretório por vez (não recursivo)

Parâmetros Detalhados

remotePath (string, opcional)

O que é: Caminho do diretório no servidor FTP que será listado.

Padrão: "/" (diretório raiz)

Flow completo para testar:

{
  "name": "Teste FTP List - 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 Pasta",
        "parameters": {
          "message": "Qual pasta listar? (Ex: /uploads/)",
          "variableName": "pasta"
        }
      }
    },
    {
      "id": "ftp_1",
      "type": "ftp",
      "position": { "x": 500, "y": 100 },
      "data": {
        "label": "Listar Arquivos",
        "parameters": {
          "host": "ftp.example.com",
          "username": "user",
          "password": "pass",
          "operation": "list",
          "remotePath": "{{pasta}}",
          "outputVariable": "lista_arquivos"
        }
      }
    },
    {
      "id": "message_1",
      "type": "message",
      "position": { "x": 700, "y": 100 },
      "data": {
        "label": "Mostrar Resultado",
        "parameters": {
          "message": "Encontrados {{lista_arquivos.count}} arquivos em {{pasta}}"
        }
      }
    },
    {
      "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/". Sistema lista arquivos desta pasta.

outputVariable (string, opcional)

O que é: Nome da variável onde resultado da listagem será armazenado.

Padrão: "ftp_result"

Flow completo para testar:

{
  "name": "Teste FTP List - 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": "Listar com Variável Customizada",
        "parameters": {
          "host": "ftp.backup.com",
          "username": "backup",
          "password": "pass",
          "operation": "list",
          "remotePath": "/backups/",
          "outputVariable": "backups_disponiveis"
        }
      }
    },
    {
      "id": "message_1",
      "type": "message",
      "position": { "x": 500, "y": 100 },
      "data": {
        "label": "Mostrar Detalhes",
        "parameters": {
          "message": "Total: {{backups_disponiveis.count}} backups\nPasta: {{backups_disponiveis.path}}"
        }
      }
    },
    {
      "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 em {{backups_disponiveis.files}} é array de arquivos encontrados.

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 "list"
remotePath string Não Diretório a listar (padrão: /)
outputVariable string Não Variável de resultado (padrão: ftp_result)

Exemplo 1: Listar e Contar Arquivos CSV

Objetivo: Verificar quantos CSVs foram depositados na pasta de importação

JSON para Importar

{
  "name": "Listar CSVs Disponíveis",
  "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": "Listar Pasta Imports",
        "parameters": {
          "host": "ftp.parceiro.com",
          "port": 21,
          "username": "importacao",
          "password": "pass123",
          "operation": "list",
          "remotePath": "/imports/csv/",
          "outputVariable": "lista_csv"
        }
      }
    },
    {
      "id": "message_1",
      "type": "message",
      "position": { "x": 500, "y": 100 },
      "data": {
        "label": "Mostrar Resultado",
        "parameters": {
          "message": "📋 Arquivos encontrados: {{lista_csv.count}}\nPasta: {{lista_csv.path}}\n\nPronto para processar!"
        }
      }
    },
    {
      "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" }
  ]
}

Saída esperada:

Sistema: 📋 Arquivos encontrados: 12
Pasta: /imports/csv/

Pronto para processar!

Exemplo 2: Listar e Mostrar Detalhes de Cada Arquivo

Objetivo: Obter lista detalhada com nome, tamanho e data de cada arquivo

JSON para Importar

{
  "name": "Listar Arquivos Detalhados",
  "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": "Listar Documentos",
        "parameters": {
          "host": "ftp.docs.com",
          "username": "documents",
          "password": "pass",
          "operation": "list",
          "remotePath": "/invoices/pending/",
          "outputVariable": "invoices"
        }
      }
    },
    {
      "id": "message_1",
      "type": "message",
      "position": { "x": 500, "y": 100 },
      "data": {
        "label": "Resumo",
        "parameters": {
          "message": "📂 Diretório: {{invoices.path}}\n📊 Total de arquivos: {{invoices.count}}\n\nUse LOOP para processar cada arquivo!"
        }
      }
    },
    {
      "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" }
  ]
}

Saída esperada:

Sistema: 📂 Diretório: /invoices/pending/
📊 Total de arquivos: 27

Use LOOP para processar cada arquivo!

Exemplo 3: Verificar Se Arquivo Específico Existe

Objetivo: Listar diretório e verificar se arquivo esperado foi depositado

JSON para Importar

{
  "name": "Verificar Arquivo Existe",
  "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": "Arquivo Esperado",
        "parameters": {
          "variableName": "arquivo_buscar",
          "value": "pedidos_2025-01-15.csv"
        }
      }
    },
    {
      "id": "ftp_1",
      "type": "ftp",
      "position": { "x": 500, "y": 100 },
      "data": {
        "label": "Listar Pasta",
        "parameters": {
          "host": "ftp.partner.com",
          "username": "sync",
          "password": "pass",
          "operation": "list",
          "remotePath": "/exports/daily/",
          "outputVariable": "arquivos_disponiveis"
        }
      }
    },
    {
      "id": "message_1",
      "type": "message",
      "position": { "x": 700, "y": 100 },
      "data": {
        "label": "Informar Status",
        "parameters": {
          "message": "🔍 Buscando: {{arquivo_buscar}}\n📁 Total de arquivos: {{arquivos_disponiveis.count}}\n\nVerifique array em {{arquivos_disponiveis.files}}"
        }
      }
    },
    {
      "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: 🔍 Buscando: pedidos_2025-01-15.csv
📁 Total de arquivos: 8

Verifique array em {{arquivos_disponiveis.files}}

Resposta do Node

{
  "success": true,
  "data": {
    "ftp_result": {
      "success": true,
      "path": "/imports/csv/",
      "count": 3,
      "files": [
        {
          "name": "pedidos_2025-01-15.csv",
          "type": "file",
          "size": 1048576,
          "modifiedAt": "2025-01-15T08:00:00.000Z",
          "permissions": "-rw-r--r--",
          "user": "ftpuser",
          "group": "ftpgroup",
          "isDirectory": false,
          "isFile": true,
          "isSymbolicLink": false
        },
        {
          "name": "produtos.csv",
          "type": "file",
          "size": 524288,
          "modifiedAt": "2025-01-14T10:30:00.000Z",
          "permissions": "-rw-r--r--",
          "user": "ftpuser",
          "group": "ftpgroup",
          "isDirectory": false,
          "isFile": true,
          "isSymbolicLink": false
        },
        {
          "name": "backup",
          "type": "directory",
          "size": 0,
          "modifiedAt": "2025-01-10T15:00:00.000Z",
          "permissions": "drwxr-xr-x",
          "user": "ftpuser",
          "group": "ftpgroup",
          "isDirectory": true,
          "isFile": false,
          "isSymbolicLink": false
        }
      ]
    },
    "operation": "list",
    "host": "ftp.parceiro.com",
    "timestamp": "2025-01-15T09:00:00.000Z"
  },
  "executionTime": 890,
  "logs": [
    "Listed 3 files in: /imports/csv/"
  ]
}

Boas Práticas

SIM:

  • Use FTP_LIST antes de baixar múltiplos arquivos
  • Verifique count para saber se há arquivos para processar
  • Itere sobre files array com node LOOP para processar em lote
  • Filtre por tipo usando isFile ou isDirectory
  • Ordene por modifiedAt para processar arquivos mais recentes primeiro

NÃO:

  • Não assuma que diretório sempre terá arquivos (pode estar vazio)
  • Não liste diretórios enormes sem necessidade (pode ser lento)
  • Não confunda type: "file" com type: "directory"
  • Não ignore permissões - verifique se tem acesso antes de baixar/apagar

Dicas

💡 Dica 1: Array files contém objetos com: name, type, size, modifiedAt, permissions, isFile, isDirectory.

💡 Dica 2: Use CONDITION node para verificar se arquivo específico está na lista: {{lista.files}} contains "nome.csv"

💡 Dica 3: Para processar todos os arquivos, combine FTP_LIST + LOOP + FTP_DOWNLOAD.

💡 Dica 4: Tamanho em bytes. Para MB: divida por 1048576. Ex: 1048576 bytes = 1 MB.

Próximos Nodes

FTP_DOWNLOAD - Baixar arquivos da lista → FTP_DELETE - Apagar arquivo da lista → LOOP - Iterar sobre array de arquivos → CONDITION - Filtrar arquivos por nome ou tamanho