diff --git a/docs/articles/logging.html b/docs/articles/logging.html
index a41dd626..b9618f29 100644
--- a/docs/articles/logging.html
+++ b/docs/articles/logging.html
@@ -104,7 +104,7 @@
{
class Program
{
- static async Task Main(string[] args)
+ static void Main(string[] args)
{
// Configure Serilog
Log.Logger = new LoggerConfiguration()
@@ -140,13 +140,13 @@
var ftpServerHost = serviceProvider.GetRequiredService<IFtpServerHost>();
// Start the FTP server
- await ftpServerHost.StartAsync();
+ ftpServerHost.StartAsync().Wait();
Console.WriteLine("Press ENTER/RETURN to close the test application.");
Console.ReadLine();
// Stop the FTP server
- await ftpServerHost.StopAsync();
+ ftpServerHost.StopAsync().Wait();
}
}
}
@@ -221,7 +221,7 @@ Registering NLog in Program.cs
{
class Program
{
- static async Task Main()
+ static void Main(string[] args)
{
// Setup dependency injection
var services = new ServiceCollection();
@@ -256,13 +256,13 @@ Registering NLog in Program.cs
var ftpServerHost = serviceProvider.GetRequiredService<IFtpServerHost>();
// Start the FTP server
- await ftpServerHost.StartAsync();
+ ftpServerHost.StartAsync().Wait();
Console.WriteLine("Press ENTER/RETURN to close the test application.");
Console.ReadLine();
// Stop the FTP server
- await ftpServerHost.StopAsync();
+ ftpServerHost.StopAsync().Wait();
}
}
}
diff --git a/docs/articles/quickstart-aspnetcore-host.html b/docs/articles/quickstart-aspnetcore-host.html
index 276c5ddc..39cc8f4e 100644
--- a/docs/articles/quickstart-aspnetcore-host.html
+++ b/docs/articles/quickstart-aspnetcore-host.html
@@ -91,6 +91,11 @@ Adding the NuGet packages
dotnet add package FubarDev.FtpServer.FileSystem.DotNet
Create an IHostedService
implementation
+
+
Important
+
This is only required for version 3.0, because the FTP server will
+provide a much tighter ASP.NET Core integration in a future release.
+
Create a new file named HostedFtpService.cs
, which contains the following code:
using System.Threading;
using System.Threading.Tasks;
diff --git a/docs/articles/quickstart-generic-host.html b/docs/articles/quickstart-generic-host.html
index 66ce411d..ac4de701 100644
--- a/docs/articles/quickstart-generic-host.html
+++ b/docs/articles/quickstart-generic-host.html
@@ -94,6 +94,11 @@ Adding the NuGet packages
dotnet add package FubarDev.FtpServer.FileSystem.DotNet
Create an IHostedService
implementation
+
+
Important
+
This is only required for version 3.0, because the FTP server will
+provide a much tighter ASP.NET Core integration in a future release.
+
Create a new file named HostedFtpService.cs
, which contains the following code:
using System.Threading;
using System.Threading.Tasks;
diff --git a/docs/articles/quickstart.html b/docs/articles/quickstart.html
index fe55eda5..73f1027a 100644
--- a/docs/articles/quickstart.html
+++ b/docs/articles/quickstart.html
@@ -109,7 +109,7 @@ Using the FTP server
{
class Program
{
- static async Task Main(string[] args)
+ static void Main(string[] args)
{
// Setup dependency injection
var services = new ServiceCollection();
@@ -135,13 +135,13 @@ Using the FTP server
var ftpServerHost = serviceProvider.GetRequiredService<IFtpServerHost>();
// Start the FTP server
- await ftpServerHost.StartAsync();
+ ftpServerHost.StartAsync().Wait();
Console.WriteLine("Press ENTER/RETURN to close the test application.");
Console.ReadLine();
// Stop the FTP server
- await ftpServerHost.StopAsync();
+ ftpServerHost.StopAsync().Wait();
}
}
}
diff --git a/docs/index.html b/docs/index.html
index f568585f..2e8afde9 100644
--- a/docs/index.html
+++ b/docs/index.html
@@ -106,13 +106,13 @@ What does it look like?
var ftpServerHost = serviceProvider.GetRequiredService<IFtpServerHost>();
// Start the FTP server
- await ftpServerHost.StartAsync();
+ ftpServerHost.StartAsync().Wait();
Console.WriteLine("Press ENTER/RETURN to close the test application.");
Console.ReadLine();
// Stop the FTP server
- await ftpServerHost.StopAsync();
+ ftpServerHost.StopAsync().Wait();
}
ASP.NET Core integration
You can also add the FTP server to your ASP.NET Core application by
diff --git a/docs/index.json b/docs/index.json
index de55b724..20860bb5 100644
--- a/docs/index.json
+++ b/docs/index.json
@@ -1,4 +1,14 @@
{
+ "articles/quickstart-aspnetcore-host.html": {
+ "href": "articles/quickstart-aspnetcore-host.html",
+ "title": "Your first FTP server | FTP Server documentation",
+ "keywords": "Creating a project mkdir TestAspNetCoreHost cd TestAspNetCoreHost dotnet new web --no-https Adding the NuGet packages # For the main FTP server dotnet add package FubarDev.FtpServer # For the System.IO-based file system access dotnet add package FubarDev.FtpServer.FileSystem.DotNet Create an IHostedService implementation Important This is only required for version 3.0, because the FTP server will provide a much tighter ASP.NET Core integration in a future release. Create a new file named HostedFtpService.cs , which contains the following code: using System.Threading; using System.Threading.Tasks; using FubarDev.FtpServer; using Microsoft.Extensions.Hosting; namespace TestAspNetCoreHost { internal class HostedFtpService : IHostedService { private readonly IFtpServerHost _ftpServerHost; /// /// Initializes a new instance of the class. /// /// The FTP server host that gets wrapped as a hosted service. public HostedFtpService( IFtpServerHost ftpServerHost) { _ftpServerHost = ftpServerHost; } /// public Task StartAsync(CancellationToken cancellationToken) { return _ftpServerHost.StartAsync(cancellationToken); } /// public Task StopAsync(CancellationToken cancellationToken) { return _ftpServerHost.StopAsync(cancellationToken); } } } Using the FTP server Change your Program.cs to the following code: using System.IO; using FubarDev.FtpServer; using FubarDev.FtpServer.FileSystem.DotNet; using Microsoft.AspNetCore.Hosting; using Microsoft.Extensions.DependencyInjection; using Microsoft.Extensions.Hosting; namespace TestAspNetCoreHost { public class Program { public static void Main(string[] args) { CreateHostBuilder(args).Build().Run(); } public static IHostBuilder CreateHostBuilder(string[] args) => Host.CreateDefaultBuilder(args) .ConfigureServices( services => { // Add FTP server services // DotNetFileSystemProvider = Use the .NET file system functionality // AnonymousMembershipProvider = allow only anonymous logins services .AddFtpServer( builder => builder .UseDotNetFileSystem() .EnableAnonymousAuthentication()); // Configure the FTP server services.Configure(opt => opt.ServerAddress = \"*\"); // use %TEMP%/TestFtpServer as root folder services.Configure(opt => opt .RootPath = Path.Combine(Path.GetTempPath(), \"TestFtpServer\")); // Add the FTP server as hosted service services .AddHostedService(); }) .ConfigureWebHostDefaults(webBuilder => { webBuilder.UseStartup(); }); } } Starting the FTP server dotnet run Now your FTP server should be accessible at 127.0.0.1:21 ."
+ },
+ "articles/quickstart-generic-host.html": {
+ "href": "articles/quickstart-generic-host.html",
+ "title": "Your first FTP server | FTP Server documentation",
+ "keywords": "Creating a project mkdir TestGenericHost cd TestGenericHost dotnet new console Adding the NuGet packages # For dependency injection support (required) dotnet add package Microsoft.Extensions.DependencyInjection # For the main FTP server dotnet add package FubarDev.FtpServer # For the System.IO-based file system access dotnet add package FubarDev.FtpServer.FileSystem.DotNet Create an IHostedService implementation Important This is only required for version 3.0, because the FTP server will provide a much tighter ASP.NET Core integration in a future release. Create a new file named HostedFtpService.cs , which contains the following code: using System.Threading; using System.Threading.Tasks; using FubarDev.FtpServer; using Microsoft.Extensions.Hosting; namespace TestGenericHost { internal class HostedFtpService : IHostedService { private readonly IFtpServerHost _ftpServerHost; /// /// Initializes a new instance of the class. /// /// The FTP server host that gets wrapped as a hosted service. public HostedFtpService( IFtpServerHost ftpServerHost) { _ftpServerHost = ftpServerHost; } /// public Task StartAsync(CancellationToken cancellationToken) { return _ftpServerHost.StartAsync(cancellationToken); } /// public Task StopAsync(CancellationToken cancellationToken) { return _ftpServerHost.StopAsync(cancellationToken); } } } Using the FTP server Change your Program.cs to the following code: using System; using System.IO; using System.Threading.Tasks; using FubarDev.FtpServer; using FubarDev.FtpServer.FileSystem.DotNet; using Microsoft.Extensions.DependencyInjection; using Microsoft.Extensions.Hosting; namespace TestGenericHost { class Program { static Task Main() { var hostBuilder = new HostBuilder() .UseConsoleLifetime() .ConfigureServices( (hostContext, services) => { // Add FTP server services // DotNetFileSystemProvider = Use the .NET file system functionality // AnonymousMembershipProvider = allow only anonymous logins services .AddFtpServer(builder => builder .UseDotNetFileSystem() .EnableAnonymousAuthentication()); // Configure the FTP server services.Configure(opt => opt.ServerAddress = \"127.0.0.1\"); // use %TEMP%/TestFtpServer as root folder services.Configure(opt => opt .RootPath = Path.Combine(Path.GetTempPath(), \"TestFtpServer\")); // Add the FTP server as hosted service services .AddHostedService(); }); var host = hostBuilder.Build(); return host.RunAsync(); } } } Starting the FTP server dotnet run Now your FTP server should be accessible at 127.0.0.1:21 ."
+ },
"api/FubarDev.FtpServer.Features.IConnectionFeature.html": {
"href": "api/FubarDev.FtpServer.Features.IConnectionFeature.html",
"title": "Interface IConnectionFeature | FTP Server documentation",
@@ -1709,31 +1719,11 @@
"title": "Upgrade from 2.x to 3.0 | FTP Server documentation",
"keywords": "Overview File system changes Authorization/authentication as per RFC 2228 Account directories queryable Membership provider changes Connection Connection data changes Data connections FTP middleware FTP request middleware FTP command execution middleware Server commands CloseConnectionServerCommand SendResponseServerCommand FTP command execution FtpContext Command handlers (and attributes) Command extensions (and attributes) FEAT support Internals FTP command collection changes Changelog What's new? What's changed? What's fixed? A look into the future Overview After the upgrade 3.0, you'll see that the IFtpServer.Start and IFtpServer.Stop functions are deprecated. Please query the IFtpServerHost instead and use the StartAsync and StopAsync functions instead. You will notice breaking changes in the following areas: File system Membership provider Command handlers (and attributes) Command extensions (and attributes) FEAT support Connection FTP command collection File system changes There are two important changes: IFileSystemClassFactory.Create now requires an IAccountInformation parameter The IUnixFileSystemEntry doesn't contain the FileSystem property anymore. Authorization/authentication as per RFC 2228 The authorization/authentication stack is new and implemented as specified in the RFC 2228 . This results in additional interfaces/extension points, like IAuthorizationMechanism IAuthenticationMechanism There is also a new extension point for actions to be called when the user is fully authorized: IAuthorizationAction . You can develop your own action, but you should only use an IAuthorizationAction.Level below 1000. The values from 1000 (incl.) to 2000 (incl.) are reserved by the FTP server and are used to initialize the FTP connection data. Account directories queryable A new interface has been introduced to get the root and home directories for a given user. Type name Description SingleRootWithoutHomeAccountDirectoryQuery Provides a single root for all users. RootPerUserAccountDirectoryQuery Gives every user its own root directory. Useful, when - for example - the file system root was set to /home . PamAccountDirectoryQuery Uses home directory information from PAM. The home directory can be configured to be the root instead. Membership provider changes The membership provider is now asynchronous which means that the ValidateUser function was renamed to ValidateUserAsync . Everything else is the same. Connection The IFtpConnection API was heavily overhauled to use a feature collection, where the features can be queried through the Features property. Using the WriteAsync function is obsolete. The FTP command handlers should use the CommandContext s ServerCommandWriter if they need to send out-of-band responses. Obsolete property Target feature Encoding IEncodingFeature OriginalStream ISecureConnectionFeature SocketStream ISecureConnectionFeature IsSecure ISecureConnectionFeature Obsolete method New home WriteAsync FtpCommandHandler.CommandContext.ResponseWriter or FtpCommandHandlerExtension.CommandContext.ResponseWriter Connection data changes The whole FtpConnectionData class is marked as obsolete. The connection datas IsAnonymous property is obsolete. An anonymous user is now detected by testing if the FtpConnectionData.User implements IAnonymousFtpUser . Most of the properties of IFtpConnection.Data were moved to a corresponding feature. Obsolete property Target feature NlstEncoding IEncodingFeature User IAuthorizationInformationFeature FileSystem IFileSystemFeature Path IFileSystemFeature CurrentDirectory IFileSystemFeature Language ILocalizationFeature Catalog ILocalizationFeature TransferMode ITransferConfigurationFeature PortAddress Removed TransferTypeCommandUsed Removed RestartPosition IRestCommandFeature RenameFrom IRenameCommandFeature ActiveMlstFacts IMlstFactsFeature PassiveSocketClient Removed BackgroundCommandHandler IBackgroundTaskLifetimeFeature CreateEncryptedStream ISecureConnectionFeature There's no direct replacement for the UserData property, but you can use the feature collection too. Data connections We're now using two factories to create data connections: ActiveDataConnectionFeatureFactory for active data connections ( PORT / EPRT commands) PassiveDataConnectionFeatureFactory for passive data connections ( PASV / EPSV commands) This factories create a IFtpDataConnectionFeature which is used to create IFtpDataConnection implementations. This allows us to abstract away the differences between active and passive data connections. The function IFtpConnection.CreateResponseSocket was replaced by IFtpConnection.OpenDataConnectionAsync and returns a IFtpDataConnection implementation. This function also takes care of SSL/TLS encryption as it wraps the IFtpDataConnection implementation returned by the IFtpDataConnectionFeature into a new IFtpDataConnection implementation with the help of the SecureDataConnectionWrapper . The extension method SendResponseAsync on the IFtpConnection was replaced by SendDataAsync and takes care of closing the IFtpDataConnection . FTP middleware There are two types of middlewares: FTP request middleware (between FTP command collection and dispatch) FTP command execution middleware (between FTP command dispatch and execution) FTP request middleware This middleware allows interception and modification of the received FTP commands. You must implement and register the IFtpMiddleware interface as service in your dependency injection container. FTP command execution middleware The difference between this and the former middleware is, that the FTP command handler for the FTP command is already selected and you can only intercept the FTP commands or do something special. You must implement and register the IFtpCommandMiddleware interface as service in your dependency injection container. An example is the FsIdChanger in the TestFtpServer project. This middleware sets - for every authenticated user - the UID/GID for file system access. Server commands We're now supporting custom FTP server commands. Those commands must implement IServerCommand and must have a corresponding handler ( IServerCommandHandler ). CloseConnectionServerCommand This command closes the FTP connection. SendResponseServerCommand This command sends a response to the client. FTP command execution Massive changes were done to the FTP command execution. The center of this changes is the new FtpContext which provides a new way to access all necessary information like the FTP connection, the command information and a channel to send server commands (which replaces IFtpConnection.WriteAsync ). FtpContext The new FtpContext is the FTP servers equivalent of ASP.NET Core's HttpContext and provides access to all information required to execute the FTP commands. Command handlers (and attributes) The command handlers were overhauled in the following areas: Lazy initialization Removed commands from DI container You can still add your FTP command handlers to the DI container, but those may (most likely) be ignored from version 4.0 and up. Implement your own IFtpCommandHandlerScanner or reuse AssemblyFtpCommandHandlerScanner New IFtpCommandHandlerScanner which scans for types that may implement FTP command handlers New IFtpCommandHandlerProvider which returns information for all found FTP command handler types Attributes for command information FtpCommandHandlerAttribute which gives the FTP command handler a name and defines if it needs a successful login or if it's abortable Simplified constructor due to CommandContext (type FtpCommandHandlerContext ) property injection Activated (read: instantiated with property injection) by command name using the IFtpCommandActivator service Command extensions (and attributes) The command extensions cannot be returned by IFtpCommandHandler.GetExtensions() anymore. The extensions were moved to their own file and the default extensions are automatically registered as service. Lazy initialization Removed command extensions from DI container You can still add your FTP command handler extensions to the DI container, but those may (most likely) be ignored from version 4.0 and up. Implement your own IFtpCommandHandlerExtensionScanner or reuse AssemblyFtpCommandHandlerExtensionScanner New IFtpCommandHandlerExtensionScanner which scans for types that may implement FTP command handler extensions New IFtpCommandHandlerExtensionProvider which returns information for all found FTP command handler extension types Attributes for command extension information FtpCommandHandlerExtensionAttribute which gives the FTP command handler extension a name and defines the command it extends and if it needs a successful login Simplified constructor due to CommandContext (type FtpCommandHandlerContext ) property injection Automatic indirect activation (read: instantiation with property injection) for the command it belongs to through the IFtpCommandActivator service FEAT support There are two new attributes to get the string to be returned by a FEAT command: FtpFeatureTextAttribute contains the feature text itself FtpFeatureFunctionAttribute contains the name of the static function to be called to get the feature text Internals FTP command collection changes We're now using ReadOnlySpan for both TelnetInputParser and FtpCommandCollector . Changelog What's new? In-memory file system Unix file system Passive data connection port range (contribution from 40three GmbH) New IFtpServerHost interface New IFtpService interface which allows easy integration into ASP.NET Core New IAccountInformation interface New IAnonymousFtpUser interface New RFC 2228 compliant authentication/authorization Root and home directories for an account can be queried New IFtpMiddleware interface for custom request middleware New IFtpCommandMiddleware interface for custom command execution middleware What's changed? Google drive upload without background uploader The IFtpCommandHandler.GetExtensions() is now deprecated as all extensions that were previously returned here have their own implementation now BREAKING: Usage of ReadOnlySpan in the FTP command collector BREAKING: IFileSystemClassFactory.Create takes an IAccountInformation BREAKING: The IMembershipProvider is now asynchronous BREAKING: FtpConnectionData.IsAnonymous is obsolete, the anonymous user is now of type IAnonymousFtpUser BREAKING: Moved PromiscuousPasv into PasvCommandOptions BREAKING: Removed property PortAddress , TransferTypeCommandUsed , and PassiveSocketClient from FtpConnectionData , because we're using a new IFtpDataConnection abstraction What's fixed? AUTH TLS fails gracefully when no SSL certificate is configured SITE BLST works again Fixed deadlock in MultiBindingTcpListener Thread safe increment/decrement for connection counter (fixes #68 ) The . directory will be returned again (fixes #56 ) A look into the future The 4.x version will drop support for .NET Standard 1.3 and - most likely - .NET 4.6.1 as the FTP Server will be reimplemented as ConnectionHandler which will result into the following improvements: Easy hosting in an ASP.NET Core application Using the ASP.NET Core connection state management"
},
- "articles/intro.html": {
- "href": "articles/intro.html",
- "title": "Install from NuGet.org | FTP Server documentation",
- "keywords": "Install from NuGet.org The project is split into multiple packages: Package Description FubarDev.FtpServer The FTP server implementation FubarDev.FtpServer.Abstractions The base classes/interfaces; Reference this to implement custom commands, file systems, authentication FubarDev.FtpServer.Commands The FTP commands implemented for this FTP server FubarDev.FtpServer.FileSystem.DotNet The System.IO-based file system access FubarDev.FtpServer.FileSystem.GoogleDrive Google Drive as virtual file system Getting Started Check out the tour of FluentMigrator in our Quickstart Basic topics Configuration Logging Authentication File Systems Advanced topics Logging FTPS Google Drive Custom File System Development Custom Account Management"
- },
- "articles/logging.html": {
- "href": "articles/logging.html",
- "title": "FTP Server logging | FTP Server documentation",
- "keywords": "Introduction The FTP server utilizes Microsoft.Extensions.Logging which provides an interface to many logging frameworks (e.g. NLog ). Example: Using SeriLog Adding SeriLog to the project Go to the quickstart project created during the Quickstart tutorial and add the following NuGet packages: # Serilog.Extensions.Logging dotnet add package Serilog.Extensions.Logging # Serilog.Sinks.Console dotnet add package Serilog.Sinks.Console Configure serilog in Program.cs Add the highlighted lines to your Program.cs: using System; using System.IO; using FubarDev.FtpServer; using FubarDev.FtpServer.FileSystem.DotNet; using Microsoft.Extensions.DependencyInjection; using Serilog; namespace QuickStart { class Program { static async Task Main(string[] args) { // Configure Serilog Log.Logger = new LoggerConfiguration() .MinimumLevel.Verbose() .Enrich.FromLogContext() .WriteTo.Console() .CreateLogger(); // Setup dependency injection var services = new ServiceCollection(); // Add Serilog as logger provider services.AddLogging(lb => lb.AddSerilog()); // use %TEMP%/TestFtpServer as root folder services.Configure(opt => opt .RootPath = Path.Combine(Path.GetTempPath(), \"TestFtpServer\")); // Add FTP server services // DotNetFileSystemProvider = Use the .NET file system functionality // AnonymousMembershipProvider = allow only anonymous logins services.AddFtpServer(builder => builder .UseDotNetFileSystem() // Use the .NET file system functionality .EnableAnonymousAuthentication()); // allow anonymous logins // Configure the FTP server services.Configure(opt => opt.ServerAddress = \"127.0.0.1\"); // Build the service provider using (var serviceProvider = services.BuildServiceProvider()) { // Initialize the FTP server var ftpServerHost = serviceProvider.GetRequiredService(); // Start the FTP server await ftpServerHost.StartAsync(); Console.WriteLine(\"Press ENTER/RETURN to close the test application.\"); Console.ReadLine(); // Stop the FTP server await ftpServerHost.StopAsync(); } } } } Now you can see all the log messages from the FTP server. Example: Using NLog Adding NLog to the project Go to the quickstart project created during the Quickstart tutorial and add the following NuGet package: # Add NLog dotnet add package NLog.Extensions.Logging Add the NLog configuration Now add a file called nlog.config with the following contents: Add the configuration to the project Change the csproj file by adding the following lines: Exe netcoreapp2.2 QuickStart PreserveNewest This ensures that the nlog.config file gets copied into the build output folder and is available for the application. Registering NLog in Program.cs using System; using System.IO; using FubarDev.FtpServer; using FubarDev.FtpServer.FileSystem.DotNet; using Microsoft.Extensions.DependencyInjection; using Microsoft.Extensions.Logging; using NLog.Extensions.Logging; namespace QuickStart { class Program { static async Task Main() { // Setup dependency injection var services = new ServiceCollection(); // Add logging services.AddLogging(lb => lb.SetMinimumLevel(LogLevel.Trace)); // use %TEMP%/TestFtpServer as root folder services.Configure(opt => opt .RootPath = Path.Combine(Path.GetTempPath(), \"TestFtpServer\")); // Add FTP server services // DotNetFileSystemProvider = Use the .NET file system functionality // AnonymousMembershipProvider = allow only anonymous logins services.AddFtpServer(builder => builder .UseDotNetFileSystem() // Use the .NET file system functionality .EnableAnonymousAuthentication()); // allow anonymous logins // Configure the FTP server services.Configure(opt => opt.ServerAddress = \"127.0.0.1\"); // Build the service provider using (var serviceProvider = services.BuildServiceProvider()) { var loggerFactory = serviceProvider.GetRequiredService(); //configure NLog loggerFactory.AddNLog(new NLogProviderOptions { CaptureMessageTemplates = true, CaptureMessageProperties = true }); NLog.LogManager.LoadConfiguration(\"nlog.config\"); // Initialize the FTP server var ftpServerHost = serviceProvider.GetRequiredService(); // Start the FTP server await ftpServerHost.StartAsync(); Console.WriteLine(\"Press ENTER/RETURN to close the test application.\"); Console.ReadLine(); // Stop the FTP server await ftpServerHost.StopAsync(); } } } } Now you can see all the log messages from the FTP server."
- },
"articles/authentication.html": {
"href": "articles/authentication.html",
"title": "Authentication | FTP Server documentation",
"keywords": "Introduction The FTP server currently supports the following membership providers: AnonymousMembershipProvider is the only portable membership provider in the project PamMembershipProvider requres .NET Core 3.0 and a system with an installed libpam.so.0 How it works The FTP server queries all services implementing the IMembershipProvider interface and tries to authenticate the given login/password against all registered providers. The first provider that was able to authenticate the user is stored in the FTP connection data. Warning The order of the registration of the membership providers is important. Anonymous authentication The anonymous authentiation is implemented by the AnonymousMembershipProvider class and can be configured by adding a service for an IAnonymousPasswordValidator . Default anonymous password validators NoValidation : Take the password without validation NoTopLevelDomainValidation : The E-Mail-Address doesn't need to have a TLD SimpleMailAddressValidation : Simple E-Mail validation BlockAnonymousValidation : Block anonymous logins The SimpleMailAddressValidation is the default password validator."
},
- "articles/quickstart.html": {
- "href": "articles/quickstart.html",
- "title": "Your first FTP server | FTP Server documentation",
- "keywords": "Creating a project mkdir ftpserver cd ftpserver dotnet new console Adding the NuGet packages # For dependency injection support (required) dotnet add package Microsoft.Extensions.DependencyInjection # For the main FTP server dotnet add package FubarDev.FtpServer # For the System.IO-based file system access dotnet add package FubarDev.FtpServer.FileSystem.DotNet Using the FTP server Change your Program.cs to the following code: using System; using System.IO; using System.Threading; using System.Threading.Tasks; using FubarDev.FtpServer; using FubarDev.FtpServer.FileSystem.DotNet; using Microsoft.Extensions.DependencyInjection; namespace QuickStart { class Program { static async Task Main(string[] args) { // Setup dependency injection var services = new ServiceCollection(); // use %TEMP%/TestFtpServer as root folder services.Configure(opt => opt .RootPath = Path.Combine(Path.GetTempPath(), \"TestFtpServer\")); // Add FTP server services // DotNetFileSystemProvider = Use the .NET file system functionality // AnonymousMembershipProvider = allow only anonymous logins services.AddFtpServer(builder => builder .UseDotNetFileSystem() // Use the .NET file system functionality .EnableAnonymousAuthentication()); // allow anonymous logins // Configure the FTP server services.Configure(opt => opt.ServerAddress = \"127.0.0.1\"); // Build the service provider using (var serviceProvider = services.BuildServiceProvider()) { // Initialize the FTP server var ftpServerHost = serviceProvider.GetRequiredService(); // Start the FTP server await ftpServerHost.StartAsync(); Console.WriteLine(\"Press ENTER/RETURN to close the test application.\"); Console.ReadLine(); // Stop the FTP server await ftpServerHost.StopAsync(); } } } } Starting the FTP server dotnet run Now your FTP server should be accessible at 127.0.0.1:21 ."
- },
- "articles/quickstart-aspnetcore-host.html": {
- "href": "articles/quickstart-aspnetcore-host.html",
- "title": "Your first FTP server | FTP Server documentation",
- "keywords": "Creating a project mkdir TestAspNetCoreHost cd TestAspNetCoreHost dotnet new web --no-https Adding the NuGet packages # For the main FTP server dotnet add package FubarDev.FtpServer # For the System.IO-based file system access dotnet add package FubarDev.FtpServer.FileSystem.DotNet Create an IHostedService implementation Create a new file named HostedFtpService.cs , which contains the following code: using System.Threading; using System.Threading.Tasks; using FubarDev.FtpServer; using Microsoft.Extensions.Hosting; namespace TestAspNetCoreHost { internal class HostedFtpService : IHostedService { private readonly IFtpServerHost _ftpServerHost; /// /// Initializes a new instance of the class. /// /// The FTP server host that gets wrapped as a hosted service. public HostedFtpService( IFtpServerHost ftpServerHost) { _ftpServerHost = ftpServerHost; } /// public Task StartAsync(CancellationToken cancellationToken) { return _ftpServerHost.StartAsync(cancellationToken); } /// public Task StopAsync(CancellationToken cancellationToken) { return _ftpServerHost.StopAsync(cancellationToken); } } } Using the FTP server Change your Program.cs to the following code: using System.IO; using FubarDev.FtpServer; using FubarDev.FtpServer.FileSystem.DotNet; using Microsoft.AspNetCore.Hosting; using Microsoft.Extensions.DependencyInjection; using Microsoft.Extensions.Hosting; namespace TestAspNetCoreHost { public class Program { public static void Main(string[] args) { CreateHostBuilder(args).Build().Run(); } public static IHostBuilder CreateHostBuilder(string[] args) => Host.CreateDefaultBuilder(args) .ConfigureServices( services => { // Add FTP server services // DotNetFileSystemProvider = Use the .NET file system functionality // AnonymousMembershipProvider = allow only anonymous logins services .AddFtpServer( builder => builder .UseDotNetFileSystem() .EnableAnonymousAuthentication()); // Configure the FTP server services.Configure(opt => opt.ServerAddress = \"*\"); // use %TEMP%/TestFtpServer as root folder services.Configure(opt => opt .RootPath = Path.Combine(Path.GetTempPath(), \"TestFtpServer\")); // Add the FTP server as hosted service services .AddHostedService(); }) .ConfigureWebHostDefaults(webBuilder => { webBuilder.UseStartup(); }); } } Starting the FTP server dotnet run Now your FTP server should be accessible at 127.0.0.1:21 ."
- },
"articles/project-structure.html": {
"href": "articles/project-structure.html",
"title": "FTP Server Project Structure | FTP Server documentation",
@@ -1769,14 +1759,24 @@
"title": "FTP Server Configuration | FTP Server documentation",
"keywords": "Introduction The configuration is split into several parts: Services IFtpServerBuilder is the FTP Server configuration builder FtpServerOptions for the FTP server transport configuration FtpConnectionOptions to configure the default control connection text encoding AuthTlsOptions for the FTPS configuration DotNetFileSystemOptions to configure the file system access SystCommandOptions to specify the behavior of the SYST command Services You use a ServiceCollection and add your services to, e.g.: var services = new ServiceCollection() .AddFtpServer(builder => builder .EnableAnonymousAuthentication() .UseDotNetFileSystem()); This is also the absolute minimum configuration for the FTP server. IFtpServerBuilder This is the place where other services are configured that will be used by the FTP server. This are the options currently available: builder.EnableAnonymousAuthentication() : Enables anonymous authentication builder.UseDotNetFileSystem() : Uses a System.IO-based file systme builder.UseGoogleDrive(...) : Uses Google Drive as virtual file system FtpServerOptions This configures the address/host/port used by the server to listen for connections. The default value is localhost as address (IPv4 and IPv6 - if available) and 21 as port. FtpConnectionOptions This may be used to configure a different default character encoding. The default value is ASCII. AuthTlsOptions This configuration option allows the specification of an X509Certificate2 (with private key) that will be used to initiate encrypted connections. DotNetFileSystemOptions Used to configure the behavior of the System.IO-based file system access, like: The path to the root directory Usage of the user ID as subdirectory Is deletion of non-empty directories allowed? SystCommandOptions Here you can specify the operating system to be returned by the SYST command."
},
- "articles/quickstart-generic-host.html": {
- "href": "articles/quickstart-generic-host.html",
- "title": "Your first FTP server | FTP Server documentation",
- "keywords": "Creating a project mkdir TestGenericHost cd TestGenericHost dotnet new console Adding the NuGet packages # For dependency injection support (required) dotnet add package Microsoft.Extensions.DependencyInjection # For the main FTP server dotnet add package FubarDev.FtpServer # For the System.IO-based file system access dotnet add package FubarDev.FtpServer.FileSystem.DotNet Create an IHostedService implementation Create a new file named HostedFtpService.cs , which contains the following code: using System.Threading; using System.Threading.Tasks; using FubarDev.FtpServer; using Microsoft.Extensions.Hosting; namespace TestGenericHost { internal class HostedFtpService : IHostedService { private readonly IFtpServerHost _ftpServerHost; /// /// Initializes a new instance of the class. /// /// The FTP server host that gets wrapped as a hosted service. public HostedFtpService( IFtpServerHost ftpServerHost) { _ftpServerHost = ftpServerHost; } /// public Task StartAsync(CancellationToken cancellationToken) { return _ftpServerHost.StartAsync(cancellationToken); } /// public Task StopAsync(CancellationToken cancellationToken) { return _ftpServerHost.StopAsync(cancellationToken); } } } Using the FTP server Change your Program.cs to the following code: using System; using System.IO; using System.Threading.Tasks; using FubarDev.FtpServer; using FubarDev.FtpServer.FileSystem.DotNet; using Microsoft.Extensions.DependencyInjection; using Microsoft.Extensions.Hosting; namespace TestGenericHost { class Program { static Task Main() { var hostBuilder = new HostBuilder() .UseConsoleLifetime() .ConfigureServices( (hostContext, services) => { // Add FTP server services // DotNetFileSystemProvider = Use the .NET file system functionality // AnonymousMembershipProvider = allow only anonymous logins services .AddFtpServer(builder => builder .UseDotNetFileSystem() .EnableAnonymousAuthentication()); // Configure the FTP server services.Configure(opt => opt.ServerAddress = \"127.0.0.1\"); // use %TEMP%/TestFtpServer as root folder services.Configure(opt => opt .RootPath = Path.Combine(Path.GetTempPath(), \"TestFtpServer\")); // Add the FTP server as hosted service services .AddHostedService(); }); var host = hostBuilder.Build(); return host.RunAsync(); } } } Starting the FTP server dotnet run Now your FTP server should be accessible at 127.0.0.1:21 ."
+ "articles/logging.html": {
+ "href": "articles/logging.html",
+ "title": "FTP Server logging | FTP Server documentation",
+ "keywords": "Introduction The FTP server utilizes Microsoft.Extensions.Logging which provides an interface to many logging frameworks (e.g. NLog ). Example: Using SeriLog Adding SeriLog to the project Go to the quickstart project created during the Quickstart tutorial and add the following NuGet packages: # Serilog.Extensions.Logging dotnet add package Serilog.Extensions.Logging # Serilog.Sinks.Console dotnet add package Serilog.Sinks.Console Configure serilog in Program.cs Add the highlighted lines to your Program.cs: using System; using System.IO; using FubarDev.FtpServer; using FubarDev.FtpServer.FileSystem.DotNet; using Microsoft.Extensions.DependencyInjection; using Serilog; namespace QuickStart { class Program { static void Main(string[] args) { // Configure Serilog Log.Logger = new LoggerConfiguration() .MinimumLevel.Verbose() .Enrich.FromLogContext() .WriteTo.Console() .CreateLogger(); // Setup dependency injection var services = new ServiceCollection(); // Add Serilog as logger provider services.AddLogging(lb => lb.AddSerilog()); // use %TEMP%/TestFtpServer as root folder services.Configure(opt => opt .RootPath = Path.Combine(Path.GetTempPath(), \"TestFtpServer\")); // Add FTP server services // DotNetFileSystemProvider = Use the .NET file system functionality // AnonymousMembershipProvider = allow only anonymous logins services.AddFtpServer(builder => builder .UseDotNetFileSystem() // Use the .NET file system functionality .EnableAnonymousAuthentication()); // allow anonymous logins // Configure the FTP server services.Configure(opt => opt.ServerAddress = \"127.0.0.1\"); // Build the service provider using (var serviceProvider = services.BuildServiceProvider()) { // Initialize the FTP server var ftpServerHost = serviceProvider.GetRequiredService(); // Start the FTP server ftpServerHost.StartAsync().Wait(); Console.WriteLine(\"Press ENTER/RETURN to close the test application.\"); Console.ReadLine(); // Stop the FTP server ftpServerHost.StopAsync().Wait(); } } } } Now you can see all the log messages from the FTP server. Example: Using NLog Adding NLog to the project Go to the quickstart project created during the Quickstart tutorial and add the following NuGet package: # Add NLog dotnet add package NLog.Extensions.Logging Add the NLog configuration Now add a file called nlog.config with the following contents: Add the configuration to the project Change the csproj file by adding the following lines: Exe netcoreapp2.2 QuickStart PreserveNewest This ensures that the nlog.config file gets copied into the build output folder and is available for the application. Registering NLog in Program.cs using System; using System.IO; using FubarDev.FtpServer; using FubarDev.FtpServer.FileSystem.DotNet; using Microsoft.Extensions.DependencyInjection; using Microsoft.Extensions.Logging; using NLog.Extensions.Logging; namespace QuickStart { class Program { static void Main(string[] args) { // Setup dependency injection var services = new ServiceCollection(); // Add logging services.AddLogging(lb => lb.SetMinimumLevel(LogLevel.Trace)); // use %TEMP%/TestFtpServer as root folder services.Configure(opt => opt .RootPath = Path.Combine(Path.GetTempPath(), \"TestFtpServer\")); // Add FTP server services // DotNetFileSystemProvider = Use the .NET file system functionality // AnonymousMembershipProvider = allow only anonymous logins services.AddFtpServer(builder => builder .UseDotNetFileSystem() // Use the .NET file system functionality .EnableAnonymousAuthentication()); // allow anonymous logins // Configure the FTP server services.Configure(opt => opt.ServerAddress = \"127.0.0.1\"); // Build the service provider using (var serviceProvider = services.BuildServiceProvider()) { var loggerFactory = serviceProvider.GetRequiredService(); //configure NLog loggerFactory.AddNLog(new NLogProviderOptions { CaptureMessageTemplates = true, CaptureMessageProperties = true }); NLog.LogManager.LoadConfiguration(\"nlog.config\"); // Initialize the FTP server var ftpServerHost = serviceProvider.GetRequiredService(); // Start the FTP server ftpServerHost.StartAsync().Wait(); Console.WriteLine(\"Press ENTER/RETURN to close the test application.\"); Console.ReadLine(); // Stop the FTP server ftpServerHost.StopAsync().Wait(); } } } } Now you can see all the log messages from the FTP server."
+ },
+ "articles/intro.html": {
+ "href": "articles/intro.html",
+ "title": "Install from NuGet.org | FTP Server documentation",
+ "keywords": "Install from NuGet.org The project is split into multiple packages: Package Description FubarDev.FtpServer The FTP server implementation FubarDev.FtpServer.Abstractions The base classes/interfaces; Reference this to implement custom commands, file systems, authentication FubarDev.FtpServer.Commands The FTP commands implemented for this FTP server FubarDev.FtpServer.FileSystem.DotNet The System.IO-based file system access FubarDev.FtpServer.FileSystem.GoogleDrive Google Drive as virtual file system Getting Started Check out the tour of FluentMigrator in our Quickstart Basic topics Configuration Logging Authentication File Systems Advanced topics Logging FTPS Google Drive Custom File System Development Custom Account Management"
},
"index.html": {
"href": "index.html",
"title": "FTP server | FTP Server documentation",
- "keywords": "FTP server This FTP Server is a pure .NET implementation with the following goals: Easy to use Extensible Virtual file system support User-defined authentication Getting started There is a quickstart tutorial available. What does it look like? // Setup dependency injection var services = new ServiceCollection(); // use %TEMP%/TestFtpServer as root folder services.Configure(opt => opt .RootPath = Path.Combine(Path.GetTempPath(), \"TestFtpServer\")); // Add FTP server services // DotNetFileSystemProvider = Use the .NET file system functionality // AnonymousMembershipProvider = allow only anonymous logins services.AddFtpServer(builder => builder .UseDotNetFileSystem() // Use the .NET file system functionality .EnableAnonymousAuthentication()); // allow anonymous logins // Configure the FTP server services.Configure(opt => opt.ServerAddress = \"127.0.0.1\"); // Build the service provider using (var serviceProvider = services.BuildServiceProvider()) { // Initialize the FTP server var ftpServerHost = serviceProvider.GetRequiredService(); // Start the FTP server await ftpServerHost.StartAsync(); Console.WriteLine(\"Press ENTER/RETURN to close the test application.\"); Console.ReadLine(); // Stop the FTP server await ftpServerHost.StopAsync(); } ASP.NET Core integration You can also add the FTP server to your ASP.NET Core application by following the instructions in this quickstart tutorial for ASP.NET Core . Further information You find more information on the articles overview ."
+ "keywords": "FTP server This FTP Server is a pure .NET implementation with the following goals: Easy to use Extensible Virtual file system support User-defined authentication Getting started There is a quickstart tutorial available. What does it look like? // Setup dependency injection var services = new ServiceCollection(); // use %TEMP%/TestFtpServer as root folder services.Configure(opt => opt .RootPath = Path.Combine(Path.GetTempPath(), \"TestFtpServer\")); // Add FTP server services // DotNetFileSystemProvider = Use the .NET file system functionality // AnonymousMembershipProvider = allow only anonymous logins services.AddFtpServer(builder => builder .UseDotNetFileSystem() // Use the .NET file system functionality .EnableAnonymousAuthentication()); // allow anonymous logins // Configure the FTP server services.Configure(opt => opt.ServerAddress = \"127.0.0.1\"); // Build the service provider using (var serviceProvider = services.BuildServiceProvider()) { // Initialize the FTP server var ftpServerHost = serviceProvider.GetRequiredService(); // Start the FTP server ftpServerHost.StartAsync().Wait(); Console.WriteLine(\"Press ENTER/RETURN to close the test application.\"); Console.ReadLine(); // Stop the FTP server ftpServerHost.StopAsync().Wait(); } ASP.NET Core integration You can also add the FTP server to your ASP.NET Core application by following the instructions in this quickstart tutorial for ASP.NET Core . Further information You find more information on the articles overview ."
+ },
+ "articles/quickstart.html": {
+ "href": "articles/quickstart.html",
+ "title": "Your first FTP server | FTP Server documentation",
+ "keywords": "Creating a project mkdir ftpserver cd ftpserver dotnet new console Adding the NuGet packages # For dependency injection support (required) dotnet add package Microsoft.Extensions.DependencyInjection # For the main FTP server dotnet add package FubarDev.FtpServer # For the System.IO-based file system access dotnet add package FubarDev.FtpServer.FileSystem.DotNet Using the FTP server Change your Program.cs to the following code: using System; using System.IO; using System.Threading; using System.Threading.Tasks; using FubarDev.FtpServer; using FubarDev.FtpServer.FileSystem.DotNet; using Microsoft.Extensions.DependencyInjection; namespace QuickStart { class Program { static void Main(string[] args) { // Setup dependency injection var services = new ServiceCollection(); // use %TEMP%/TestFtpServer as root folder services.Configure(opt => opt .RootPath = Path.Combine(Path.GetTempPath(), \"TestFtpServer\")); // Add FTP server services // DotNetFileSystemProvider = Use the .NET file system functionality // AnonymousMembershipProvider = allow only anonymous logins services.AddFtpServer(builder => builder .UseDotNetFileSystem() // Use the .NET file system functionality .EnableAnonymousAuthentication()); // allow anonymous logins // Configure the FTP server services.Configure(opt => opt.ServerAddress = \"127.0.0.1\"); // Build the service provider using (var serviceProvider = services.BuildServiceProvider()) { // Initialize the FTP server var ftpServerHost = serviceProvider.GetRequiredService(); // Start the FTP server ftpServerHost.StartAsync().Wait(); Console.WriteLine(\"Press ENTER/RETURN to close the test application.\"); Console.ReadLine(); // Stop the FTP server ftpServerHost.StopAsync().Wait(); } } } } Starting the FTP server dotnet run Now your FTP server should be accessible at 127.0.0.1:21 ."
}
}
\ No newline at end of file
diff --git a/docs/manifest.json b/docs/manifest.json
index 4be65d86..c79bbe6d 100644
--- a/docs/manifest.json
+++ b/docs/manifest.json
@@ -4218,7 +4218,7 @@
"output": {
".html": {
"relative_path": "articles/logging.html",
- "hash": "BowAtF2haDmW8iOXQaVL6Q=="
+ "hash": "g6T+xTnC4zQ3pcVmJRj3hA=="
}
},
"is_incremental": false,
@@ -4242,7 +4242,7 @@
"output": {
".html": {
"relative_path": "articles/quickstart-aspnetcore-host.html",
- "hash": "2VaDlYqtkmYZJW2vdd8H6w=="
+ "hash": "2iWE8NWh0tyGAP+BI7IY/A=="
}
},
"is_incremental": false,
@@ -4254,7 +4254,7 @@
"output": {
".html": {
"relative_path": "articles/quickstart-generic-host.html",
- "hash": "3zlYF3cpOhTHYCfHN/4ptw=="
+ "hash": "tEbwooyK0VzW4TQPxNoDbw=="
}
},
"is_incremental": false,
@@ -4266,7 +4266,7 @@
"output": {
".html": {
"relative_path": "articles/quickstart.html",
- "hash": "zS7jAo+ki7eFYpIufjC9OQ=="
+ "hash": "c0kEn7+RR0cd1ygalZPlgQ=="
}
},
"is_incremental": false,
@@ -4302,7 +4302,7 @@
"output": {
".html": {
"relative_path": "index.html",
- "hash": "SmBbnywEtsTEPtXuy9DiaA=="
+ "hash": "ycpfc50ZOy8j8Mf980ahIQ=="
}
},
"is_incremental": false,
@@ -4330,13 +4330,6 @@
"skipped_file_count": 0
},
"processors": {
- "TocDocumentProcessor": {
- "can_incremental": false,
- "details": "Processor TocDocumentProcessor cannot support incremental build because the processor doesn't implement ISupportIncrementalDocumentProcessor interface.",
- "incrementalPhase": "build",
- "total_file_count": 0,
- "skipped_file_count": 0
- },
"ManagedReferenceDocumentProcessor": {
"can_incremental": true,
"incrementalPhase": "build",
@@ -4347,7 +4340,14 @@
"can_incremental": true,
"incrementalPhase": "build",
"total_file_count": 16,
- "skipped_file_count": 15
+ "skipped_file_count": 14
+ },
+ "TocDocumentProcessor": {
+ "can_incremental": false,
+ "details": "Processor TocDocumentProcessor cannot support incremental build because the processor doesn't implement ISupportIncrementalDocumentProcessor interface.",
+ "incrementalPhase": "build",
+ "total_file_count": 0,
+ "skipped_file_count": 0
}
}
},