CopyToSFTPObserver é um Worker Service em .NET 9 que automatiza transferência e processamento de arquivos entre pastas locais e destinos SFTP. O serviço lê um arquivo de mapeamento (apptasks.json) que descreve pastas e uma sequência ordenada de tarefas a serem executadas (copiar, checar, mover, deletar, inspecionar e notificar). Possui logger customizado (arquivo), envio de e-mail e validação robusta da configuração.
- Ler e validar
apptasks.json. - Para cada
FolderMap, gerar e executar uma sequência ordenada deTasksMaps. - Copiar arquivos para SFTP, verificar presença no SFTP, mover/excluir arquivos localmente e notificar por e-mail.
- Registrar logs em arquivo com rotação básica.
Os nomes de classes e caminhos abaixo seguem a estrutura da solução.
-
Program(Program.cs)- Inicializa o host, configura
AppSettingsviabuilder.Configuration, injeta serviços e registra oWorker. - Configura logger customizado (
AddFileLogger) e console (AddCustomConsole).
- Inicializa o host, configura
-
Worker(Worker.cs) — herdaBackgroundService- Ciclo de vida:
StartAsync,StopAsync(logs). ExecuteAsync: loop principal que obtémAppTaskviaAppTaskMapperConfigurator.MapAppTask()e chamaProcessFolders(...)repetidamente segundoIntervaloEntreExecucoes.- Métodos-chave:
ProcessFolders(IEnumerable<FolderMap>, CancellationToken)ProcessSingleFolder(FolderMap, CancellationToken)— geraTaskActionsa partir deTasksMaps.ExecuteTasks(List<TaskActions>, FolderMap, CancellationToken)— executa ações em ordem, trata falhas e envia notificações.HandleTaskFailure(TaskActions, FolderMap)— move arquivos para pasta de erro e registra falhas.ProximaExecucao(CancellationToken)— delay entre execuções.
- Ciclo de vida:
-
AppTaskMapperConfigurator(Infrastructure/AppTaskMapperConfigurator.cs)MapAppTask()— lêapptasks.json, valida a estrutura JSON, deserializa paraAppTaske valida conteúdo.- Realiza validações de presença de
Name,Version,FolderMapse valida cadaFolderMap.
-
Modelos (
Models):AppTask(Models/MappingTasks/AppTask.cs) —Name,Version,IEnumerable<FolderMap> FolderMaps.FolderMap(Models/MappingTasks/FolderMap.cs) —Name,FolderPathOrigin,SFTPPathDestination,ProcessedFilesOnError,ProcessedFilesOnSuccess,EmailNotify,InspectLocation,IEnumerable<TasksMap> TasksMaps. Método:GetFiles().TasksMap(Models/MappingTasks/TaskMap.cs) —Name,Order,Task.TaskActions(Models/MappingTasks/TaskActions.cs) — representa ação pronta:Action(TypeOfTasks),Argument1..Argument5,ExecuteCopy/Check/Move(implementadas no modelo/fábricas).TypeOfTasks(Models/Enums/TypeOfTasks.cs) — valores:copy,check,move,delete,notify,inspect.
-
Fábricas e infraestrutura:
TaskActionFactory(Infrastructure/Factorys/TaskActionFactory.cs) —CreateTaskAction(string task, FolderMap folderMap, string taskName)interpreta a stringTaske criaTaskActions, resolvendo variáveis.DeleteFileFactory/ demais fábricas para operações locais.Email(Infrastructure/Email/Email.cs) — construtor e métodoSend()que usaEmailCredentialsestático comSmtpClient.SFTPCredentials,EmailCredentials,AppSettings(Models/Configurations) — modelos de configurações e credenciais.AppSettingspossui lógica para decodificar valores base64 (SFTP e senha de e-mail).
-
Logger customizado (
Services/CustomLogger):FileLogger,FileLoggerProvider,FileLoggerConfiguration— grava logs em arquivo (processlog_yyyyMMdd_HHmmss.log), rotação por tamanho e diretório configurável.
appsettings.json(valores podem ser fornecidos via variáveis de ambiente ou outros providers). OProgramfazbuilder.Configuration.Bind(appSettings); as chaves devem corresponder às propriedades deAppSettings.
Exemplo mínimo (valores sensíveis podem ser Base64):
{
"SFTPUrl": "sftp://exemplo.com",
"UsuarioSFTP": "usuario",
"Senha": "senha_ou_base64",
"EMAIL_FROM": "seu@dominio.com",
"EMAIL_SENHA": "senha_email_ou_base64",
"EMAIL_PORT": 587,
"EMAIL_HOST": "smtp.exemplo.com",
"IntervaloEntreExecucoes": 60000,
"LogFile": "logs",
"Port": 22
}AppSettingstentará decodificarSFTPUrl,UsuarioSFTP,SenhaeEMAIL_SENHAcomo base64; se falhar, usa o valor original.IntervaloEntreExecucoesem milissegundos.LogFileé o diretório relativo para logs (padrãocopyToSFTPObserverLogger).
apptasks.json(arquivo obrigatório na pasta de execução do serviço). Exemplo atualizado para propriedades reais:
{
"Name": "Monitoramento de pastas - Exemplo",
"Version": "1.0",
"FolderMaps": [
{
"Name": "Processando pasta de entrada",
"FolderPathOrigin": "C:\\Temp\\inConnect\\out",
"SFTPPathDestination": "SFTP:/inConnect/Teste",
"ProcessedFilesOnError": "C:\\Temp\\inConnect\\error",
"ProcessedFilesOnSuccess": "C:\\Temp\\inConnect\\processed",
"EmailNotify": "ops@exemplo.com",
"InspectLocation": "",
"TasksMaps": [
{
"Name": "Copiando para SFTP | copy:@SFTPPathDestination",
"Order": 1,
"Task": "copy:@FolderPathOrigin:@SFTPPathDestination"
},
{
"Name": "Verificando no SFTP | check:@SFTPPathDestination",
"Order": 2,
"Task": "check:@FolderPathOrigin:@SFTPPathDestination"
},
{
"Name": "Movendo para processed | move:@FolderPathOrigin:@ProcessedFilesOnSuccess",
"Order": 3,
"Task": "move:@FolderPathOrigin:@ProcessedFilesOnSuccess"
},
{
"Name": "Notificar | notify",
"Order": 4,
"Task": "notify"
}
]
}
]
}- Nas strings
Taskuse:para separar tipo e argumentos; a fábrica suporta até 5 argumentos. - Em
TasksMaps.Namepode-se usar@Variavelpara gerar textos dinâmicos (resolvidos viaExtractVariable/GetValue).
-
Abra a solução no Visual Studio ou use CLI:
- Build:
dotnet build - Run:
dotnet run --project .\SftpSyncTool\SftpSyncTool.csproj
- Build:
-
Coloque
apptasks.jsonna pasta de execução (bin\Debug\net9.0ou pasta de publicação). -
Configure
appsettings.jsonou variáveis de ambiente conforme exemplo.
Opção A — Executável (Windows):
dotnet publish -c Release -r win-x64ou usar Publish no Visual Studio.- Copie a pasta publicada para o servidor.
- Registre como serviço Windows (ex.:
sc create CopyToSFTPObserver binPath= "C:\\Caminho\\CopyToSFTPObserver.exe" start= auto).
Opção B — Container:
dotnet publish -c Release -r linux-x64e crie imagem Docker; monteapptasks.jsoneappsettings.jsonvia volumes.
- Logs em arquivos gerenciados por
FileLoggerProviderno diretório deAppSettings.LogFile. - Em caso de erro:
apptasks.jsonnão encontrado: verifique se o arquivo foi copiado para a pasta do executável.- Erros de SFTP: verifique
SFTPUrl,UsuarioSFTP,SenhaePortemappsettings.json. - Erros de e-mail: verifique
EMAIL_HOST,EMAIL_PORT,EMAIL_FROMeEMAIL_SENHA.
AppTaskMapperConfiguratorvalida o JSON e não permite execução se o arquivo estiver inválido.
- Valores sensíveis podem ser codificados em base64;
AppSettingstentará decodificá-los automaticamente. - Em produção, prefira armazenar segredos em provedores seguros (Azure Key Vault, AWS Secrets Manager, variáveis de ambiente ou User Secrets em desenvolvimento).
- Coloque breakpoints em
Worker.ExecuteAsync,AppTaskMapperConfigurator.MapAppTask()eTaskActionFactory.CreateTaskAction()para investigar fluxo e resolução de variáveis. - Valide
apptasks.jsoncom um linter JSON antes de executar o serviço.
Program.cs— bootstrap e DI.Worker.cs— execução das tarefas.Infrastructure/—AppTaskMapperConfigurator, fábricas,Email.Models/—AppSettings,AppTask,FolderMap,TasksMap,TaskActions, enums.Services/CustomLogger— logger de arquivo.
- Rode localmente e valide logs antes de abrir PR.
- Siga padrões existentes para novos tipos de tarefas e fábricas.