Here is my example of async version of
FluentFTP using
log4net with TextBoxAppender which I already described
here
For this example I have added following NuGet packages:
FluentFTP
FluentFTP.Logging
log4net
Microsoft.Extensions.Configuration.Json - this package I needed because user name and pass for FTP I have saved in JSON configuration file.
In short code looks like this:
Log4NetLogger log4NetLogger = new Log4NetLogger(log);
AsyncFtpClient client = new AsyncFtpClient(host, user, pass);
client.ValidateCertificate += OnValidateCertificate;
client.Logger = new FtpLogAdapter(log4NetLogger);
await client.AutoConnect();
await client.UploadFile(fileName, "/public_html/kmlTestDelete/test.kml");
private void OnValidateCertificate(BaseFtpClient control, FtpSslValidationEventArgs e)
{
e.Accept = true;
}
The method OnValidateCertificate I am using to accept any certificate, this part of code I took from
here
Class Log4NetLogger looks like this:
using log4net;
using Microsoft.Extensions.Logging;
using ILogger = Microsoft.Extensions.Logging.ILogger;
namespace FluentFTPasyncExample;
public class Log4NetLogger : ILogger
{
private readonly ILog _log;
public Log4NetLogger(ILog log)
{
_log = log;
}
public void Log<TState>(LogLevel logLevel, EventId eventId, TState state, Exception exception, Func<TState, Exception, string> formatter)
{
string message = $"{formatter(state, exception)} {exception}";
if (!string.IsNullOrEmpty(message))
{
switch (logLevel)
{
case LogLevel.Critical:
_log.Fatal(message);
break;
case LogLevel.Debug:
case LogLevel.Trace:
_log.Debug(message);
break;
case LogLevel.Error:
_log.Error(message);
break;
case LogLevel.Information:
_log.Info(message);
break;
case LogLevel.Warning:
_log.Warn(message);
break;
default:
_log.Warn($"Encountered unknown log level {logLevel}, writing out as Info.");
_log.Info(message, exception);
break;
}
}
}
public bool IsEnabled(LogLevel logLevel)
{
switch (logLevel)
{
case LogLevel.Critical:
return _log.IsFatalEnabled;
case LogLevel.Debug:
case LogLevel.Trace:
return _log.IsDebugEnabled;
case LogLevel.Error:
return _log.IsErrorEnabled;
case LogLevel.Information:
return _log.IsInfoEnabled;
case LogLevel.Warning:
return _log.IsWarnEnabled;
default:
throw new ArgumentOutOfRangeException(nameof(logLevel));
}
}
public IDisposable BeginScope<TState>(TState state)
{
return null!;
}
}
Notice that I am injecting log4net in constructor.
Example download from
here.