https://github.com/fmisrl/ftpserver
A lightweight, modern FTP server library for .NET.
https://github.com/fmisrl/ftpserver
Last synced: about 2 months ago
JSON representation
A lightweight, modern FTP server library for .NET.
- Host: GitHub
- URL: https://github.com/fmisrl/ftpserver
- Owner: fmisrl
- License: mit
- Created: 2026-04-13T11:24:06.000Z (2 months ago)
- Default Branch: master
- Last Pushed: 2026-04-13T14:34:17.000Z (2 months ago)
- Last Synced: 2026-04-13T15:13:10.939Z (2 months ago)
- Language: C#
- Size: 36.1 KB
- Stars: 0
- Watchers: 0
- Forks: 0
- Open Issues: 0
-
Metadata Files:
- Readme: README.md
- License: LICENSE.txt
Awesome Lists containing this project
README
# FmiSrl.FtpServer
[](https://github.com/fmisrl/ftpserver/actions/workflows/publish.yml)
A lightweight, modern FTP server library for .NET.
## Features
- Fully asynchronous operation.
- Supports both Dependency Injection and manual instantiation.
- Extensible authentication and file system providers.
- Built-in support for common FTP commands (USER, PASS, LIST, RETR, STOR, etc.).
- PASV mode support.
## Installation
```bash
dotnet add package FmiSrl.FtpServer.Server
```
## Usage
### With Dependency Injection (Recommended)
To use the FTP server in a modern .NET application (e.g., ASP.NET Core, Worker Service), register it in your `Program.cs`:
```csharp
using Microsoft.Extensions.DependencyInjection;
using FmiSrl.FtpServer.Server;
using FmiSrl.FtpServer.Server.DependencyInjection;
using FmiSrl.FtpServer.Server.Services;
var builder = Host.CreateApplicationBuilder(args);
// Configure Options for Providers
builder.Services.Configure(opt =>
{
opt.RootDirectory = "./my_ftp_root";
});
builder.Services.Configure(opt =>
{
opt.Username = "admin";
opt.Password = "secure_password";
});
// Add FTP Server and configure providers via generic DI
builder.Services.AddFtpServer(options =>
{
options.FtpPort = 21;
options.ServerName = "My Custom FTP Server";
})
.UseFileSystemProvider()
.UseAuthenticationProvider();
var host = builder.Build();
// Get the server instance and start it
var ftpServer = host.Services.GetRequiredService();
await ftpServer.StartAsync();
await host.RunAsync();
```
The server is registered as a **Singleton** by default.
### Without Dependency Injection
You can also use the library in simple console applications or legacy projects without a DI container:
```csharp
using FmiSrl.FtpServer.Server;
using FmiSrl.FtpServer.Server.Services;
using Microsoft.Extensions.Logging.Abstractions;
using Microsoft.Extensions.Options;
var serverOptions = Options.Create(new FtpServerConfigurationOptions
{
FtpPort = 2121,
ServerName = "Standalone FTP Server"
});
var fsOptions = Options.Create(new PhysicalFileSystemProviderOptions
{
RootDirectory = "./ftp_root"
});
var authOptions = Options.Create(new SimpleAuthenticationProviderOptions
{
Username = "user",
Password = "password"
});
// Providers are strictly required
var ftpServer = new FtpServer(
new PhysicalFileSystemProvider(fsOptions),
new SimpleAuthenticationProvider(authOptions),
serverOptions,
NullLogger.Instance
);
await ftpServer.StartAsync();
Console.WriteLine("Server started. Press any key to stop.");
Console.ReadKey();
await ftpServer.StopAsync();
```
## Configuration
### Logging
The library uses `Microsoft.Extensions.Logging`. When using DI, it will automatically use the configured logging providers (e.g., Serilog, Console, Debug).
When used manually, you can pass any `ILogger` implementation to the constructor.
### Authentication Provider
Implement the `IAuthenticationProvider` interface to customize how users are authenticated:
```csharp
public interface IAuthenticationProvider
{
Task AuthenticateAsync(string username, string password);
}
```
### File System Provider
Implement the `IFileSystemProvider` interface to provide custom storage (e.g., Azure Blob Storage, Database, S3).
It provides an `FtpAuthenticationContext` which includes the currently authenticated username:
```csharp
using FmiSrl.FtpServer.Server.Abstractions;
public interface IFileSystemProvider
{
Task> GetEntriesAsync(FtpAuthenticationContext authContext, string path);
Task OpenReadAsync(FtpAuthenticationContext authContext, string path);
Task OpenWriteAsync(FtpAuthenticationContext authContext, string path);
Task DeleteFileAsync(FtpAuthenticationContext authContext, string path);
Task CreateDirectoryAsync(FtpAuthenticationContext authContext, string path);
Task DeleteDirectoryAsync(FtpAuthenticationContext authContext, string path);
Task FileExistsAsync(FtpAuthenticationContext authContext, string path);
Task DirectoryExistsAsync(FtpAuthenticationContext authContext, string path);
Task RenameAsync(FtpAuthenticationContext authContext, string oldPath, string newPath);
}
```