Linger.FileSystem.Ftp 2.0.0-preview.1

This is a prerelease version of Linger.FileSystem.Ftp.
dotnet add package Linger.FileSystem.Ftp --version 2.0.0-preview.1
                    
NuGet\Install-Package Linger.FileSystem.Ftp -Version 2.0.0-preview.1
                    
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="Linger.FileSystem.Ftp" Version="2.0.0-preview.1" />
                    
For projects that support PackageReference, copy this XML node into the project file to reference the package.
<PackageVersion Include="Linger.FileSystem.Ftp" Version="2.0.0-preview.1" />
                    
Directory.Packages.props
<PackageReference Include="Linger.FileSystem.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 Linger.FileSystem.Ftp --version 2.0.0-preview.1
                    
#r "nuget: Linger.FileSystem.Ftp, 2.0.0-preview.1"
                    
#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 Linger.FileSystem.Ftp@2.0.0-preview.1
                    
#: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=Linger.FileSystem.Ftp&version=2.0.0-preview.1&prerelease
                    
Install as a Cake Addin
#tool nuget:?package=Linger.FileSystem.Ftp&version=2.0.0-preview.1&prerelease
                    
Install as a Cake Tool

Linger.FileSystem.Ftp

Breaking changes and 2.0 migration notes are documented in the Linger migration guide.

Overview

Linger.FileSystem.Ftp is an implementation of the Linger FileSystem abstraction that provides FTP file operations support. It uses the FluentFTP library to offer a robust and retry-capable FTP client for common file operations such as uploading, downloading, listing, and deleting files.

Installation

dotnet add package Linger.FileSystem.Ftp

Features

  • File operations over FTP (upload, download, list, delete)
  • Configurable retry policies for unstable networks
  • Timeout configurations
  • Seamless integration with other Linger.FileSystem components
  • Supports multiple .NET frameworks (net9.0, net8.0, netstandard2.0)

Basic Usage

Creating an FTP File System Instance

// Create settings for remote FTP system
var settings = new FtpFileSystemOptions
{
    Host = "ftp.example.com",
    Port = 21,
    UserName = "username",
    Password = "password",
    ConnectionTimeout = 15000, // 15 seconds
    OperationTimeout = 60000   // 60 seconds
};

// Configure retry options
var retryOptions = new RetryOptions
{
    MaxRetryAttempts = 3,
    DelayMilliseconds = 1000,
    MaxDelayMilliseconds = 5000
};

// Create FTP file system
using var ftpSystem = new FtpFileSystem(settings, retryOptions);

// Upload a file
await using var stream = File.OpenRead("./local/file.txt");
var result = await ftpSystem.UploadAsync(stream, "/remote/path/file.txt", overwrite: true);

if (result.Success)
{
    Console.WriteLine($"Upload successful: {result.FilePath}");
}

// Download a file
var downloadResult = await ftpSystem.DownloadFileAsync("/remote/path/file.txt", "C:/Downloads/file.txt");

if (downloadResult.Success)
{
    var downloadedBytes = await ftpSystem.GetFileSizeAsync("/remote/path/file.txt");
    Console.WriteLine($"Downloaded {downloadedBytes} bytes");
}

FTP Client Encoding

FtpFileSystemOptions.Encoding configures the encoding used by the FTP client for protocol text and remote path names. It defaults to UTF-8 when omitted:

var settings = new FtpFileSystemOptions
{
    Host = "ftp.example.com",
    UserName = "username",
    Password = "password",
    Encoding = System.Text.Encoding.UTF8
};

This option does not control file-content encoding. Pass the required encoding to GetReaderAsync or GetWriterAsync when reading or writing text files.

File Upload Methods

// Method 1: Upload from stream to complete file path
await using var stream = File.OpenRead("local.txt");
var result = await ftpSystem.UploadAsync(stream, "/remote/path/file.txt", overwrite: true);

// Method 2: Upload local file to complete remote path
result = await ftpSystem.UploadFileAsync("C:/local/file.txt", "/remote/path/file.txt", overwrite: true);

Integration with Dependency Injection

// In your startup class
public void ConfigureServices(IServiceCollection services)
{
    services.AddTransient<IRemoteFileSystem>(provider => {
        var settings = new FtpFileSystemOptions
        {
            Host = "ftp.example.com",
            Port = 21,
            UserName = "username",
            Password = "password",
            ConnectionTimeout = 15000,
            OperationTimeout = 60000
        };
        
        var retryOptions = new RetryOptions
        {
            MaxRetryAttempts = 3,
            DelayMilliseconds = 1000,
            MaxDelayMilliseconds = 5000
        };
        
        return new FtpFileSystem(settings, retryOptions);
    });
}

FtpFileSystem automatically connects on the first operation and keeps one client connection per instance. Do not invoke operations concurrently on the same instance or mutate its working directory while another operation is running.

FtpFileSystem implements IAsyncRemoteFileSystem. Use the concrete type or this capability interface when asynchronous disposal is required; the general IRemoteFileSystem contract provides synchronous disposal.

Advanced Features

Working Directory Management

// Set working directory
await ftpSystem.SetWorkingDirectoryAsync("/public_html");

Directory Listing and Manipulation

// List files
var files = await ftpSystem.ListFilesAsync("/public_html");
foreach (var file in files)
{
    Console.WriteLine($"File: {file}");
}

// Create directory
await ftpSystem.CreateDirectoryIfNotExistsAsync("/public_html/uploads");

// Check if directory exists
bool exists = await ftpSystem.DirectoryExistsAsync("/public_html/uploads");

Custom Connection Settings

var settings = new FtpFileSystemOptions
{
    Host = "ftp.example.com",
    Port = 21,
    UserName = "username",
    Password = "password",
    ConnectionTimeout = 30000,           // 30 seconds connection timeout
    OperationTimeout = 120000,           // 2 minutes operation timeout
    Type = "FTP"
};

// Advanced retry configuration
var retryOptions = new RetryOptions
{
    MaxRetryAttempts = 5,
    DelayMilliseconds = 2000,
    MaxDelayMilliseconds = 30000,
    UseExponentialBackoff = true    // Use exponential backoff for retries
};

var ftpSystem = new FtpFileSystem(settings, retryOptions);

File Information and Metadata

// Get file size
long? fileSize = await ftpSystem.GetFileSizeAsync("/remote/file.txt");

// Get file last modified time
DateTime modTime = await ftpSystem.GetModifiedTimeAsync("/remote/file.txt");

// Check if file exists
bool exists = await ftpSystem.FileExistsAsync("/remote/file.txt");

Connection Lifetime

using (var ftpSystem = new FtpFileSystem(settings))
{
    // The first operation establishes the connection; disposal closes it.
    await ftpSystem.UploadFileAsync("local.txt", "/remote/path");
    await ftpSystem.DownloadFileAsync("/remote/file.txt", "downloaded.txt");
}

Error Handling and Troubleshooting

Common FTP Exceptions

try
{
    await ftpSystem.UploadFileAsync("local.txt", "/remote/path");
}
catch (FileSystemException ex)
{
    switch (ex.Operation)
    {
        case "Upload":
            Console.WriteLine($"Upload failed: {ex.Message}");
            break;
        case "Connect":
            Console.WriteLine($"Connection failed: {ex.Message}");
            break;
    }
}
catch (TimeoutException ex)
{
    Console.WriteLine($"Operation timed out: {ex.Message}");
}

Retry Configuration for Unstable Networks

var retryOptions = new RetryOptions
{
    MaxRetryAttempts = 10,             // Retry up to 10 times
    DelayMilliseconds = 1000,       // Start with 1 second delay
    MaxDelayMilliseconds = 60000,   // Maximum 60 seconds delay
    UseExponentialBackoff = true    // Increase delay exponentially
};

var ftpSystem = new FtpFileSystem(settings, retryOptions);

Dependencies

License

This project is licensed under the terms of the license provided with the Linger project.

Contributing

Contributions are welcome! Please feel free to submit a Pull Request.

Product Compatible and additional computed target framework versions.
.NET net5.0 was computed.  net5.0-windows was computed.  net6.0 was computed.  net6.0-android was computed.  net6.0-ios was computed.  net6.0-maccatalyst was computed.  net6.0-macos was computed.  net6.0-tvos was computed.  net6.0-windows was computed.  net7.0 was computed.  net7.0-android was computed.  net7.0-ios was computed.  net7.0-maccatalyst was computed.  net7.0-macos was computed.  net7.0-tvos was computed.  net7.0-windows was computed.  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. 
.NET Core netcoreapp2.0 was computed.  netcoreapp2.1 was computed.  netcoreapp2.2 was computed.  netcoreapp3.0 was computed.  netcoreapp3.1 was computed. 
.NET Standard netstandard2.0 is compatible.  netstandard2.1 was computed. 
.NET Framework net461 was computed.  net462 was computed.  net463 was computed.  net47 was computed.  net471 was computed.  net472 was computed.  net48 was computed.  net481 was computed. 
MonoAndroid monoandroid was computed. 
MonoMac monomac was computed. 
MonoTouch monotouch was computed. 
Tizen tizen40 was computed.  tizen60 was computed. 
Xamarin.iOS xamarinios was computed. 
Xamarin.Mac xamarinmac was computed. 
Xamarin.TVOS xamarintvos was computed. 
Xamarin.WatchOS xamarinwatchos 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
2.0.0-preview.1 0 8/29/2026
1.6.4 90 8/16/2026
1.6.3 94 8/5/2026
1.6.2 111 8/2/2026
1.6.0 110 7/25/2026
1.5.5 107 7/23/2026
1.5.4-preview 84 7/21/2026
1.5.3-preview 95 7/20/2026
1.5.2-preview 93 7/19/2026
1.5.1-preview 94 7/15/2026
1.5.0-preview 89 7/14/2026
1.4.4-preview 109 6/16/2026
1.4.3-preview 107 6/15/2026
1.4.2 122 5/20/2026
1.4.1-preview 109 5/12/2026
1.4.0 112 5/6/2026
1.3.3-preview 102 5/5/2026
1.3.2-preview 106 4/29/2026
1.3.1-preview 110 4/28/2026
1.3.0-preview 107 4/27/2026
Loading failed