RaFtpsClient 26.9.1
dotnet add package RaFtpsClient --version 26.9.1
NuGet\Install-Package RaFtpsClient -Version 26.9.1
<PackageReference Include="RaFtpsClient" Version="26.9.1" />
<PackageVersion Include="RaFtpsClient" Version="26.9.1" />
<PackageReference Include="RaFtpsClient" />
paket add RaFtpsClient --version 26.9.1
#r "nuget: RaFtpsClient, 26.9.1"
#:package RaFtpsClient@26.9.1
#addin nuget:?package=RaFtpsClient&version=26.9.1
#tool nuget:?package=RaFtpsClient&version=26.9.1
RaFtpsClient
Free FTP/FTPS client and class library available on any platform supporting .NET Standard 2.0+.
Written to overcome the limits of .NET's System.Net.FTPWebRequest in terms of FTPS support.
Supported Frameworks
Targets .NET Standard 2.0, so it can be referenced from .NET Framework 4.6.1+, .NET Core 2.0+ and .NET 5 and later.
Features
- FTP and FTPS (FTP over SSL/TLS) support
- Explicit and implicit SSL/TLS connections
- Active and passive data connection modes
- File upload/download with progress callbacks
- Directory listing and navigation
- File and directory management (rename, delete, create)
- Keep-alive support
- Custom FTP commands
- Certificate validation callbacks
- Synchronous and asynchronous APIs over one session, with
CancellationTokensupport
Quick Start
using RaFtpsClient;
using System.Net;
using var client = new FTPSClient();
client.Connect("ftp.example.com", new NetworkCredential("user", "pass"),
ESSLSupportMode.CredentialsRequired);
var files = client.GetDirectoryList();
foreach (var f in files)
Console.WriteLine($"{f.Name} ({f.Size} bytes)");
client.GetFile("remote.txt", "local.txt");
client.Close();
Every operation has an *Async counterpart. The two share the session, so they can be mixed:
using var client = new FTPSClient();
await client.ConnectAsync("ftp.example.com", new NetworkCredential("user", "pass"),
ESSLSupportMode.CredentialsRequired, cancellationToken: ct);
foreach (var f in await client.GetDirectoryListAsync(cancellationToken: ct))
Console.WriteLine($"{f.Name} ({f.Size} bytes)");
await client.GetFileAsync("remote.txt", "local.txt", cancellationToken: ct);
The configured timeout applies to both paths: synchronous calls through the socket timeouts,
asynchronous ones through an internal deadline that surfaces as FTPException. Cancelling a
transfer mid-way leaves the session usable; the server's abort reply is consumed for you.
TLS defaults
The TLS version is left to the operating system (SslProtocols.None), and server certificates are
checked against their revocation list. Both are configurable before Connect:
client.SslProtocols = SslProtocols.Tls12; // pin a version
client.SslCheckCertRevocation = false; // only if the CRL/OCSP endpoint is unreachable
License
Apache-2.0 - see LICENSE for details.
| Product | Versions 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 was computed. 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 was computed. 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 was computed. 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. |
-
.NETStandard 2.0
- No dependencies.
NuGet packages
This package is not used by any NuGet packages.
GitHub repositories
This package is not used by any popular GitHub repositories.
New:
- Asynchronous API: every operation has an *Async counterpart taking a CancellationToken. Both
paths share the session and the configured timeout; cancelling a transfer mid-way leaves the
session usable.
Behaviour changes:
- Server certificate revocation is checked by default (SslCheckCertRevocation to disable).
- TLS version is negotiated by the OS (SslProtocols to pin one); TLS 1.0/1.1 are no longer offered.
- A refused PROT on an implicit FTPS connection throws FTPSslException instead of silently continuing.
- The PASS argument is masked in the LogCommand event.
- KeepAliveTimeout is configurable.
Fixes:
- A recursive download with many identically named files could take minutes deduplicating
local paths; it is now linear.
- The listing parser is twice as fast and allocates half as much.
- Connect overload ignored useCtrlEndPointAddressForData.
- Keep-alive could not be restarted, and could consume a transfer's completion reply.
- Command injection through a bare CR or LF in a remote name.
- Certificate pinning compared issuer and serial only.
- PutUniqueFile returned a truncated name; SSL mode flags were corrupted after a PROT failure.
- Listings: non-ASCII names split across reads, listings of only symlinks or setgid/sticky
directories parsed as empty, one bad record discarded the whole listing, the permission field
lost its last character, and time-only dates could land in the future.
- EPSV used the local address; active mode was IPv4-only with no accept timeout; connect ignored
the timeout; a closed control connection surfaced as a null reference.