redb.Route.Ftp 2.0.2

Prefix Reserved
There is a newer version of this package available.
See the version list below for details.
dotnet add package redb.Route.Ftp --version 2.0.2
                    
NuGet\Install-Package redb.Route.Ftp -Version 2.0.2
                    
This command is intended to be used within the Package Manager Console in Visual Studio, as it uses the NuGet module's version of Install-Package.
<PackageReference Include="redb.Route.Ftp" Version="2.0.2" />
                    
For projects that support PackageReference, copy this XML node into the project file to reference the package.
<PackageVersion Include="redb.Route.Ftp" Version="2.0.2" />
                    
Directory.Packages.props
<PackageReference Include="redb.Route.Ftp" />
                    
Project file
For projects that support Central Package Management (CPM), copy this XML node into the solution Directory.Packages.props file to version the package.
paket add redb.Route.Ftp --version 2.0.2
                    
#r "nuget: redb.Route.Ftp, 2.0.2"
                    
#r directive can be used in F# Interactive and Polyglot Notebooks. Copy this into the interactive tool or source code of the script to reference the package.
#:package redb.Route.Ftp@2.0.2
                    
#:package directive can be used in C# file-based apps starting in .NET 10 preview 4. Copy this into a .cs file before any lines of code to reference the package.
#addin nuget:?package=redb.Route.Ftp&version=2.0.2
                    
Install as a Cake Addin
#tool nuget:?package=redb.Route.Ftp&version=2.0.2
                    
Install as a Cake Tool

redb.Route.Ftp

FTP/FTPS transport for the redb.Route ESB framework.
Polling consumer and atomic producer powered by FluentFTP — passive/active mode, FTPS (TLS), glob filtering, idempotency, temp-file upload, recursive directories, and jail-path protection.

NuGet License: MIT

Quick Start

// Poll remote FTP directory
.From(Ftp.Directory("/inbox")
    .Host("ftp.example.com")
    .Username("user").Password("secret")
    .Include("*.csv")
    .Delay(30000)
    .MoveTo("/inbox/archive")
    .Recursive()
    .Idempotent())

// Upload files atomically
.To(Ftp.Directory("/outbox")
    .Host("ftp.example.com")
    .Username("user").Password("secret")
    .TempPrefix(".uploading-")
    .AutoCreate())

// FTPS with passive mode
.From(Ftp.Directory("/secure")
    .Host("ftp.example.com")
    .UseFtps()
    .ValidateCertificate(false)
    .PassiveMode())

URI Format

ftp:///remote/path?host=server&port=21&username=admin&password=secret&param=value

The path part of the URI is the remote base directory. All other parameters go in the query string.

Consumer

The consumer polls a remote FTP directory at a configurable interval, delivers each file as an exchange, and then applies post-processing (delete / move / noop).

Polling Pipeline

  1. Connect to FTP server
  2. List files in the remote directory (optionally recursive)
  3. Apply filters: glob include/exclude, min/max age, idempotency, done-file check
  4. Sort results (by name, date, or size)
  5. For each file: pre-move → read body → invoke processor → post-process
  6. On failure: move file to moveFailed directory (if configured)

Consumer Headers

Header Type Description
redbFtp.Name string Full file name (with extension)
redbFtp.NameOnly string File name without extension
redbFtp.Extension string File extension (e.g. .csv)
redbFtp.RemotePath string Full remote path of the file
redbFtp.RelativePath string Path relative to the base directory
redbFtp.RemoteParent string Parent directory path
redbFtp.Length long File size in bytes
redbFtp.LastModified DateTimeOffset Last modified timestamp
redbFtp.Host string FTP host
redbFtp.Port int FTP port
redbFtp.Username string FTP username

Post-Processing Modes

Mode Description
Noop() Leave the file in place (default)
Delete() Delete after successful processing
MoveTo("/archive") Move to another directory after processing

Only one mode can be active at a time.

Idempotency

Prevents re-processing the same file. Default key: "{fullPath}|{lastModifiedUtc}|{length}".

.From(Ftp.Directory("/inbox")
    .Host("ftp.example.com")
    .Idempotent()                          // default key
    .Idempotent(Constant("${file.name}"))) // custom key expression

Done Files

Only process a file when a companion "done" marker exists:

.From(Ftp.Directory("/inbox")
    .DoneFileName(Constant("${file:name}.done")))

Supports ${file:name} and ${file:name.noext} substitutions.

Producer

The producer uploads files to the FTP server using an atomic temp-file-then-rename strategy.

Write Pipeline

  1. Resolve target file name (from options, header, or auto-generated GUID)
  2. Validate path against jail directory
  3. Create parent directories if autoCreate=true
  4. Write body to a temp file (configurable prefix/name)
  5. Handle existing file (Override / Append / Fail / Ignore / Move / TryRename)
  6. Atomically rename temp file to target

File Name Resolution

Priority order:

  1. FileName option (dynamic expression)
  2. redbFtp.Name header
  3. redbFile.Name header (generic file header)
  4. Auto-generated: redb-{GUID}

File Exist Strategies

Strategy Description
Override Overwrite existing file (default)
Append Append to existing file
Fail Throw exception
Ignore Skip silently
Move Rename existing file before writing
TryRename Try alternate names

Move Existing Strategies

When FileExist=Move, the existing file is renamed with a suffix:

Strategy Suffix Example
Timestamp .20260405143022567 (default)
Backup .bak
Guid .a1b2c3d4e5f6...

Jail Path Protection

By default (jailStartingDirectory=true), the producer rejects any path that resolves outside the base directory via .. traversal. Set JailStartingDirectory(false) to disable.

Flatten

When flatten=true, directory components in the file name are stripped — only the base name is used for the target path.

Producer Header

Header Description
redbFtp.NameProduced Full path of the written file

FTPS (FTP over TLS)

.From(Ftp.Directory("/secure")
    .Host("ftp.example.com")
    .UseFtps()                      // Explicit TLS
    .ValidateCertificate(false))    // Skip certificate validation

Uses FtpEncryptionMode.Explicit. Certificate validation is enabled by default.

Data Connection Mode

.From(Ftp.Directory("/data")
    .PassiveMode())   // default — AutoPassive

.From(Ftp.Directory("/data")
    .ActiveMode())    // AutoActive

Fluent Builder API

Category Methods
Connection .Host(), .Port(), .Username(), .Password(), .ConnectionTimeout(), .OperationTimeout(), .PassiveMode(), .ActiveMode()
TLS .UseFtps(), .ValidateCertificate()
Reconnect .MaximumReconnectAttempts(), .ReconnectDelay(), .Disconnect()
Consumer .Delay(), .InitialDelay(), .Include(), .Exclude(), .Recursive(), .MaxDepth(), .MinDepth(), .SortBy(), .MaxMessagesPerPoll(), .MinAge(), .MaxAge()
Post-process .Noop(), .Delete(), .MoveTo(), .MoveExisting(), .PreMove(), .MoveFailed()
Idempotency .Idempotent(), .DoneFileName()
Transfer .TransferType() (Binary/Ascii), .StreamBody(), .Charset(), .IgnoreFileNotFoundOrPermissionError(), .StartingDirectoryMustExist(), .SendEmptyMessageWhenIdle()
Producer .FileName(), .FileExist(), .MoveExistingFileStrategy(), .TempPrefix(), .TempFileName(), .AutoCreate(), .AllowNullBody(), .EagerDeleteTargetFile(), .Flatten(), .JailStartingDirectory(), .AppendChars()

Most builder methods accept both constant values and IExpression for runtime resolution.

Configuration Reference

Connection

Parameter Default Description
host localhost FTP server hostname
port 21 FTP server port
username FTP username
password FTP password
connectionTimeout 30000 Connection timeout (ms)
operationTimeout 60000 Operation timeout (ms)
passiveMode true Use passive data connection
useFtps false Enable FTPS (Explicit TLS)
validateCertificate true Validate server certificate
transferType Binary Binary or Ascii

Reconnection

Parameter Default Description
maximumReconnectAttempts 3 Max reconnect attempts
reconnectDelay 1000 Delay between reconnect attempts (ms)
disconnect false Disconnect after each poll/write

Consumer / Polling

Parameter Default Description
delay 60000 Poll interval (ms)
initialDelay 1000 Delay before first poll (ms)
include Glob include pattern (e.g. *.csv,*.xml)
exclude Glob exclude pattern
recursive false Recurse into subdirectories
maxDepth 0 Max recursion depth (0 = unlimited)
minDepth 0 Min depth for file selection
sortBy None Sort order: Name, NameDesc, Modified, ModifiedDesc, Size, SizeDesc
maxMessagesPerPoll 0 Max files per poll (0 = unlimited)
minAge 0 Min file age (ms)
maxAge 0 Max file age (ms, 0 = unlimited)
startingDirectoryMustExist true Fail if base directory doesn't exist
sendEmptyMessageWhenIdle false Send empty exchange when no files found

Consumer / Post-Processing

Parameter Default Description
noop false Leave file in place
delete false Delete after processing
moveTo Move after processing (expression)
preMove Move before processing (expression)
moveFailed Move on failure (expression)
moveExisting Override How to handle existing file at move target

Consumer / Idempotency

Parameter Default Description
idempotent false Enable idempotent consumer
idempotentKey Custom idempotency key expression
doneFileName Done-file pattern (e.g. ${file:name}.done)

Consumer / Body

Parameter Default Description
streamBody false true → body is Stream, falsebyte[]
charset utf-8 Character encoding

Producer

Parameter Default Description
fileName Target file name (expression)
fileExist Override Strategy: Override, Append, Fail, Ignore, Move, TryRename
moveExistingFileStrategy Timestamp Rename strategy for existing files: Backup, Timestamp, Guid
tempPrefix Temp file prefix (expression)
tempFileName Temp file name (expression)
autoCreate true Auto-create parent directories
allowNullBody false Allow null body (creates empty file)
eagerDeleteTargetFile true Delete target before writing
flatten false Strip directory components from file name
jailStartingDirectory true Reject paths outside the base directory
appendChars Characters to append after each write
ignoreFileNotFoundOrPermissionError false Ignore listing errors for missing/inaccessible dirs

DI Registration

services.AddRedbRouteFtp();

Requirements

  • .NET 8.0 / 9.0 / 10.0
  • FluentFTP 54.1.0
  • redb.Route.GenericFile (shared file transport abstractions)
Product Compatible and additional computed target framework versions.
.NET net8.0 is compatible.  net8.0-android was computed.  net8.0-browser was computed.  net8.0-ios was computed.  net8.0-maccatalyst was computed.  net8.0-macos was computed.  net8.0-tvos was computed.  net8.0-windows was computed.  net9.0 is compatible.  net9.0-android was computed.  net9.0-browser was computed.  net9.0-ios was computed.  net9.0-maccatalyst was computed.  net9.0-macos was computed.  net9.0-tvos was computed.  net9.0-windows was computed.  net10.0 is compatible.  net10.0-android was computed.  net10.0-browser was computed.  net10.0-ios was computed.  net10.0-maccatalyst was computed.  net10.0-macos was computed.  net10.0-tvos was computed.  net10.0-windows was computed. 
Compatible target framework(s)
Included target framework(s) (in package)
Learn more about Target Frameworks and .NET Standard.

NuGet packages

This package is not used by any NuGet packages.

GitHub repositories

This package is not used by any popular GitHub repositories.

Version Downloads Last Updated
3.3.3 0 7/16/2026
3.3.1 56 7/10/2026
3.3.0 86 7/8/2026
3.2.0 105 6/29/2026
3.1.0 123 6/6/2026
3.0.1 108 6/3/2026
3.0.0 104 5/29/2026
2.0.2 113 5/16/2026
2.0.0 61 5/6/2026