- Time Zones
- New: Time Zone conversion is performed using standard .NET
TimeZoneInfo
instead of hourly offset values - New:
ClientTimeZone
andServerTimeZone
Properties to configure Time Zone conversion - New:
SetClientTimeZone
andSetServerTimeZone
Utility methods to configure Time Zone conversion
- New: Time Zone conversion is performed using standard .NET
- FTP Monitoring
- New: FTP monitors to detect added/updated/deleted files in remote FTP folders and send events to your application accordingly (
FtpMonitor
,AsyncFtpMonitor
,BlockingAsyncFtpMonitor
) - New: FTP monitor event with details on changed files (
FtpMonitorEventArgs
) - New: Sample code for
BlockingAsyncFtpMonitor
- New: FTP monitors to detect added/updated/deleted files in remote FTP folders and send events to your application accordingly (
- Testing
- Fix: Total rewrite of FileZilla FTP server docker for integration testing (thanks @FanDjango)
- Fix: Updated tests for new TimeZone API
- Maintainance
- Change: Allow overriding of download/upload internal methods in FTP client subclasses (
DownloadFileInternal
andUploadFileInternal
) - Change: Refactor file transfer and file listing utilities into static module classes
- Change: Improve performance of dictionary lookups (thanks @ssg)
- Fix:
LogMaskModule
throwing exception whenUserName
is empty (thanks @ssg) - Fix: Improve
AsyncFtpClient
dispose logic and cleanup warnings on build (thanks @FanDjango)
- Change: Allow overriding of download/upload internal methods in FTP client subclasses (
- Fix: GUI hangs during
Dispose
ofAsyncFtpClient
- Fix: Improve Async & GUI cohabitation
- Change: Rename
FtpCapability.MLSD
toMLST
to better reflect its behaviour
- Connection
- New: Accurate FTP connection status tracking with the help of
NoopDaemon
(integrated intoIsConnected
API) - New: Enum
FtpConnectionState
to track FTP socket connection state - Improve: IsConnected: Handle sync/async close situations and remove unwanted
Poll
calls - Improve: Detailed logging of Close/Dispose failures for improved error reporting in user logs
- Fix: Regression where multiple sequential connects/disconnects crash the FTP Client
- New: Accurate FTP connection status tracking with the help of
- File Listing
- Fix: DrFtpd sends invalid FTP response
550
when folder exists but is empty
- Fix: DrFtpd sends invalid FTP response
- File Transfer
- Improve: Upload/Download speed calculation and improve handling of divide by zero errors
- Improve: Upload/Download log message format
- Improve: Improve file transfer performance by using the new
AsMemory
API for reading/writing data from/to the FTP socket stream in .NET 5+
- Core
- Remove:
Config.SocketPollInterval
setting, because it is no longer used or required - Improve: Dozens of log messages throughout the internal socket handling subsystem
- Improve: Documentation for
GetReply
core function - Fix: Pass missing cancellation token in async
Execute
API - Change: Disposing log messages are now Verbose instead of Warning
- Fix: Uncatchable exceptions after cancellation of read in
FtpSocketStream
- Remove:
- File Upload
- New:
FtpRemoteExists.OverwriteInPlace
mode which overwrites files without deleting them first
- New:
- Connection
- New:
FtpConfig.PostConnect
to enable the init sequence performed immediately after connection - Fix: Undetected connect timeout in .NET 5+
- Fix: Remove
BufferedStream
feature and further refactoring of Dispose logic - Fix: Use correct SSL stream
AuthenticateAsClient
API rather than outdated API - Fix: Mask the FTP server host IP in PASV response when
Config.LogHost
is set to false
- New:
- File Transfer
- Fix
DateTimes.ParseFtpDate
will consider providedformats
when parsing date/time values
- Fix
- File Listing
- Improve: Improved performance for Regex parsing by utilizing Regex caching
- Improve: Improved performance for Stream Read/Write API for .NET Standard 2.1 and newer
- Fix: Correct sequencing of FTP stream disposing for .NET Framework
- Fix: Extraneous
GetReply
call inUploadInternal
/DownloadInternal
- File Verification (thanks DasRaschloch and FanDjango)
- New: All file transfer methods now support size/checksum/date comparison
- New:
DownloadDirectory
,DownloadFile
,DownloadFiles
, support new size/checksum/date comparison - New:
UploadDirectory
,UploadFile
,UploadFiles
support new size/checksum/date comparison - New: FXP
TransferDirectory
,TransferFile
support new size/checksum/date comparison - New:
FtpVerify
has new options:Size/Date/Checksum/OnlyChecksum
- File Transfer (thanks FanDjango)
- Fix:
DownloadFile
with Progress throwsFtpException
- Fix: Correctly handle internal errors in
UploadInternal
/DownloadInternal
- Fix:
GetFileSize
provides invalid file length and transfer fails
- Fix:
- FTP Proxy (thanks zhaohuiyingxue)
- Fix:
GetListing
does not use the proxy with passive FTP
- Fix:
- FTP Disconnection (thanks FanDjango)
- New: Indicate creating/disposing sync/async connections in log
- Fix: Disconnection during Connect async needs to be awaited
- Fix: FTP
BaseClient
is alsoIAsyncDisposable
in addition toIDisposable
- Fix: Disposing a connected
AsyncFtpClient
throws non-fatalInvalidCastException
- Fix: Cloning a
AsyncFtpClient
throws non-fatalInvalidCastException
- Change:
AsyncFtpClient
to change allClose
usage toawait CloseAsync
- Change:
FtpDataStream
now supports an async close method - Change: Use
DisposeAsync
pattern forAsyncFtpClient
- Change: Call
Dispose
/DisposeAsync
onBufferedStream
instead ofFlush
/FlushAsync
- Fix: Restore call to
FtpSslStream
for graceful TLS termination
- IBM OS/400 (thanks FanDjango)
- Fix: Async server-specific post-connection commands was missing for OS400
- NOOP Daemon (thanks FanDjango)
- Fix: Improve NOOP daemon logic
- Fix: More reliable termination
- Fix: Handle NOOP API exceptions
- Fix: Handle NOOP situations in
Execute
API - Fix: No need for NOOP commands before a QUIT command
- Fix: Improve
GetReply
logging and handling for stale data and NOOP reactions - Fix: If QUIT is stashed and reconnect is pending, defer it.
- Fix: Recognize special commands & responses in all cases
- Fix: Delay NOOP connectivity tests until connection fully established
- Connection Status (thanks FanDjango)
- Fix:
IsStillConnected
: Clean upConnect
/DisconnectInternal
interface artifacts - Fix:
IsStillConnected
: Add log messages
- Fix:
- IBM OS/400 (thanks FanDjango)
- Fix: Enhance detection of IBM OS/400 servers
- Fix: Set
SITE LISTFMT 1
andSITE NAMEFMT 1
on connect
- File Transfer
- Fix:
DownloadFile
:FileCount
Progress updated even when files are skipped (thanks J0nathan550) - Fix:
DownloadFile
:stopPosition
not working in some cases (thanks alexgubanow) - Fix:
DownloadFile
: Progress calculation not correct when usingstopPosition
(thanks alexgubanow)
- Fix:
- Fix: Change semaphore logic to prevent deadlock in NOOP Daemon (thanks FanDjango)
- NOOP Daemon (thanks FanDjango)
- New: Revised NOOP handling with new config option
Noop
to enable NOOP daemon - New: New config options
NoopInactiveCommands
andNoopActiveCommands
to set FTP commands usable - New: New config option
NoopTestConnectivity
to issue NOOP commands before every FTP command - Change:
NoopInterval
now has a default of 3 minutes - Change: Update
GetReply
for new NOOP handling logic
- New: Revised NOOP handling with new config option
- Connection Status (thanks FanDjango)
- New:
IsStillConnected()
API to reliably check if FTP connection is still active
- New:
- Auto Connection (mostly thanks FanDjango)
- New: Treat timeouts during
AutoDetect
as failed detection instead of aborting (thanks FabBadDog) - Fix: Prevent Auto-Reconnect occurring before connect is complete
- Fix:
AutoDetect
is thread unsafe, fixAutoDetectConfig
IncludeImplicit
logic
- New: Treat timeouts during
- Multi-Threading (thanks FanDjango)
- Change: Remove all internal locking in the sync
FtpClient
- Change: Remove all internal locking in the sync
- FTP Transfers (thanks FanDjango)
- Fix: Servers with no server handler used wrong
GetListing()
command - Fix:
OpenRead
retry attempt fails due to typo - Fix: Missing code in async stale data handler
- Fix: Missing code in Async
DisableUTF8
API
- Fix: Servers with no server handler used wrong
- FTP Proxies
- Fix: Correctly set supported method in SOCKS 5 proxy negotiation (thanks rmja)
- Codebase Maintainance (mostly thanks FanDjango)
- Fix: Remove
NET50_OR_LATER
invalid moniker (thanks sean-bloch) - Fix: Cleanup and standardize all .NET Target framework markers (TFMs)
- Fix: Clean up interfaces and implementation for Connect/Disconnect
- Fix: Remove
- Testing (thanks FanDjango)
- Fix: Powershell folder was not being populated, add to GIT ignore list
- Fix: Docker build process was failing due to debian py image changes
- Logging (thanks FanDjango)
- New: Log selected server handler, if any are detected
- New: Log improvements for
OpenAppend
,OpenRead
andOpenWrite
to help in debugging
- Utilities
- New:
FtpResult.ToStatus()
API to easily compare result values ofDownloadFile
/DownloadFiles
andUploadFile
/UploadFiles
- New:
- File Transfer (thanks FanDjango)
- Fix: Code cleanup for FTP path and directory handling
- Fix:
CreateDirectory
sometimes needed inAutoNavigate
mode - Fix: Optimize
CWD
/PWD
directory navigation inAutoNavigate
mode - Fix: Prevent infinite loop on stale data read when FTP socket stalled
- Fix: Some FTP servers throw
450
error for empty folders
- Directory Navigation (thanks FanDjango)
- New: Add auto-navigate support to
GetCheckSum
- Fix:
UploadDirectory
withFtpNavigate.Conditional
does not auto-navigate correctly - Fix: Not all linux ftp servers support backslash as path separator character
- Fix: Cancellation token passing and await syntax for
DownloadFile
,UploadFile
,GetListing
- New: Add auto-navigate support to
- Directory Navigation
- New:
Navigate
Config setting to automatically handle FTP directory navigation - New: Download and Upload API honors
Navigate
setting - New:
GetListing
API honorsNavigate
setting
- New:
- File Transfer (thanks FanDjango)
- New:
DownloadUriBytes
API method to directly connect and download a URI/URL - Fix:
OpenRead
,OpenWrite
andOpenAppend
quirks to handle their stale data - Fix: Complete redesign of FTP socket stale data handling and
CheckStaleData
implementation
- New:
- Auto Connection (thanks FanDjango)
- New: Overloaded API
AutoDetect
with object-driven configuration usingFtpAutoDetectConfig
- New: Add options
RequireEncryption
andIncludeImplicit
toAutoDetect
to allow for more configurability during auto-connection - Fix: Improve
AutoDetect
behaviour to support various server use-cases - Fix: Add
RNFM
/RNTO
FTP commands to critical-sequence list to fix Auto-Reconnect of SSL sessions - Fix:
AutoDetect
empty config is gracefully handled
- New: Overloaded API
- Logging
- Logging (thanks FanDjango)
- New: Add exact .NET platform build target during the version logging
- File Transfer
- New: Config API
LocalFileShareOption
to allow setting file sharing mode for uploads - New: Connection type
PASVUSE
akaPassiveAllowUnroutable
- New: Add friendlier names for connection types
AutoActive
andPassiveExtended
- New: Config API
- File Hashing (thanks FanDjango)
- Fix: Parse non-standard FTP hashes for BrickFTP, Files.com, ExaVault.com
- FTP Connections (thanks FanDjango)
- Fix: SSL Buffering: Improve connection logic, update comments, refactor code
- Fix: SSL Buffering: Cannot connect to FTPS IIS server on Windows 2019 from Azure Functions V4
- Fix: Disconnection: Improve conditional compiles and test for each target in
FtpSslStream
- Fix: Disconnection: Use
ShutDownAsync
for .NET 4.7 and later - Fix:
InnerException
does not get caught during FTPS security exception - Fix: Remove dead code in SSL permanent failure detection
- Fix: Custom Stream:
PolicyErrors
not being set correctly
- File Listing (thanks FanDjango)
- Fix: Improve file name parsing logic for DOS/Windows/IIS servers
- Fix: Improved null checks for
InfoMessages
(thanks jnyrup)
- Testing (thanks FanDjango)
- Fix:
GnuTlsStream
integration tests due to invalid stream detection
- Fix:
- Fix: Custom stream logging tweak: Message first then close stream
- Fix: Custom stream: Also log
InnerException
if it exists within the exception - Fix: Internal stream null check to avoid exception in
Execute
API methods
- Fix: Hotfix to remove new
DowloadStream
overload that causes compile failure
- New: Add
stopPosition
parameter toDownloadBytes
andDowloadStream
to allow partial downloads
- New: Add 9 missing properties to the FTP client interfaces
- New: Improve log message wording for EPSV & proxies (thanks FanDjango)
- Fix: Improve GetReply to handle connection loss edge cases and timeout exceptions, possibly incurring cpu-loops (thanks FanDjango)
- Fix: Improve NOOP behavior to correctly handle timeout exceptions (thanks FanDjango)
- New:
DiscoverSslSessionLength
API to auto compute a working value for SSL Session length (thanks FanDjango)
- API: Rename
ExecuteGetText
toExecuteDownloadText
- Fix:
AsyncFtpClient.CreateDirectory
fails on freshly created client instance (thanks FanDjango)
- New:
ExecuteGetText
API to execute an FTP command and return multiline output (thanks FanDjango) - New: Integration with
FluentFTP.GnuTLS
NuGet package to allow for GnuTLS TLS 1.3 streams
- File Transfer
- New:
UploadFiles
API inAsyncFtpClient
which takes anIEnumerable<FileInfo>
- New:
UploadFiles
andDownloadFiles
now support rules which allow filtering of uploaded/downloaded files - New:
UploadFiles
andDownloadFiles
now return aList<FtpResult>
with per-file status rather than just a count - New:
FtpMissingObjectException
thrown when trying to download a non-existant object - New: Download API
DownloadDirectory
,DownloadFile
,DownloadBytes
,DownloadStream
will throwFtpMissingObjectException
rather than silently failing - New: Download API
DownloadFiles
will mark non-existant files asIsFailed
and add theException
rather than silently failing - Tests: New integration tests to check fail conditions of Download API
- Fix: Correctly detect non-existant files and folders on FileZillla server (thanks FanDjango)
- New:
- Connection
- New: Improve reconnect logic to restore working directory and ASCII/Binary data type on automatic reconnection (thanks FanDjango)
- New: Improve
Execute
logic to handle working directory on automatic reconnection (thanks FanDjango) - New: Do not attempt Reconnect if we have never been connected before (thanks FanDjango)
- Change: Reconnect logging messages elevated from
Info
toWarn
(thanks FanDjango) - Fix: Use
ConnectAsync
fornet472
platform where required (thanks jnyrup)
- Exceptions
- Logging
- New: Setting
Config.LogDurations
to configure if durations are to be logged - New: Add FTP command roundtrip duration to every
Response
log message (thanks FanDjango) - New: Smart rendering of log message durations (hours, minutes, seconds, MS)
- Fix: Improve exception handling for connection/disconnection and authentication (thanks FanDjango)
- Fix: Simplify exception handling using
when
keyword and new conditional keywords (thanks jnyrup)
- New: Setting
- Quality
- Please read the Migration Guide for help migrating to the new version!
- Packaging (thanks jnyrup)
- Core FluentFTP package has removed the dependency on MELA (Microsoft.Extensions.Logging.Abstractions)
- New FluentFTP.Logging package released that integrates with MELA
- Logging (thanks jnyrup)
FtpClient.Logger
is no longer a MELAILogger
FtpClient.Logger
is now a custom interface calledIFtpLogger
- Connection (thanks FanDjango)
- New: Save bandwidth on automatic reconnection by skipping
FEAT
command - Fix: Implementation of connection/disconnection internal logic
- Fix: Create a default
ValidateCertificate
handler if none is provided - Fix: Auto-reconnect SSL streams after a set number of replies are read
- New: Save bandwidth on automatic reconnection by skipping
- File Transfer (thanks FanDjango)
- New: Upload: Ability to upload file streams with unknown size
- Fix: Upload: Timeout detection for file streams with unknown size
- File Listings (thanks FanDjango)
- New:
SetModifiedTime
falls back toMDTM
ifMFMT
command not available - New:
GetListing
: Catch control connection loss and retry once - Fix:
GetListing
silently fails and returns empty array if connection lost - Fix: IBM OS/400: Correctly handle special chars on EBCDIC code page fault
- New:
- Tests (thanks FanDjango)
- New: Docker: Add optional path to allow the user to save disk space
- Fix: Fix many XML compiler warnings in the testing system
- FTP (thanks FanDjango)
- New: Detect Apache FTP Server (allows for future server-specific handling)
- New: Major improvements to automatic FTP reconnection on connection loss
- New: Special handling to prevent automatic FTP reconnection during critical FTP sequences
- New:
Config.SslSessionLength
setting to perform automatic reconnection to bypass SSL issues - Fix: Connect closing has been removed from
ReadStaleData
and moved intoExecute
- Fix: Improved NOOP handling by detecting more formats of NOOP FTP replies
- Fix:
IOException
edge case on FTPS connections after a certain number of FTP commands - Fix: Handle early
226 Transfer complete
edge case in FTP file download - Fix: Honor
FtpRemoteExists.NoCheck
mode inMoveFile
to prevent checking for existing files
- Tests (thanks FanDjango)
- New: Improved Docker build process using common images to speed up build times
- New: Rewrite all first-party Docker images to use pre-built common images
- New: Support for Apache FTP Server integration test server
- FTP (thanks FanDjango)
- New: DNS Caching to prevent DNS server rejecting name resolution for rapidly repeating requests
- New: Better log message for stream dispose to indicate which stream was disposed
- Fix: Typo in
FtpException
thrown when creating directories - Fix: Do not assume the server path when
CWD
command sent - Change: Refactor post-Execute operations and implement parity in sync/async API
- Connection (thanks FanDjango)
- Fix:
AutoConnect
fails with Azure FTP servers due to profile handling - Change: Improve exception throwing order for
InvalidOperationException
if unable to connect - Change: Complete rewrite of
Connect
API - New: Add check to ensure that the IP version is permitted when connecting to servers
- Fix: Implement retry logic to check all possibly server addresses before failing with an exception
- Fix: Implement improved logic to detect timeouts and socket failures
- Fix:
ConnectTimeout
is not taking effect forConnectAsync
API - Fix: Reset
CurrentDataType
when re-connected to an FTP server
- Fix:
- File Transfer (thanks FanDjango)
- Fix: Parity in resume logic for upload and download and throw
AggregateException
where required - New: Implement the missing
ResumeUpload
for synchronous API - New: Add a log message so that the resume operation is actually noticed by users
- Fix: Parity in resume logic for upload and download and throw
- FTP
- Tests
- New: Redesigned Pureftpd integration test server (thanks FanDjango)
- Proxies
- Fix: Read extra bytes to fix
GetListing
for SOCKS4 and SOCKS4a proxies (thanks FanDjango)
- Fix: Read extra bytes to fix
- Please read the Migration Guide for help migrating to the new version!
- API
- New:
LastReplies
property to fetch a list of the last 5 server replies (thanks FanDjango) - Removed:
Config.DisconnectWithShutdown
as it was not required (thanks FanDjango) - Removed:
FtpListOption.NoImage
as it was not required (thanks FanDjango) - Removed: Privatize
CurrentDataType
and removeForceSetDataType
(thanks FanDjango)
- New:
- FTP
- New: SslStream wrapper to send TLS close notifications for .NET and .NET Core (thanks FanDjango)
- Change: SSL Closure Alert is now always sent when a stream is terminated (thanks FanDjango)
- Change: Make SSL Shutdown independant of
Config.DisconnectWithShutdown
(thanks FanDjango) - Change:
GetReply
redesign: New mode to exhaustively read allNOOP
replies (thanks FanDjango)
- Logging
- Z/OS
- New: IBM OS/400: Support blanks in filename and add unit test cases (thanks FanDjango)
- Tests
- New: Support for Bftpd integration test server (thanks FanDjango)
- New: Support for ProFTPD integration test server (thanks FanDjango)
- New: Support for glFTPd integration test server (thanks FanDjango)
- New: Support for FileZilla integration test server (thanks FanDjango)
- New: Redesigned VsFTPd integration test server (thanks FanDjango)
- New: Ability to run test server containers as FTP or FTPS servers (thanks FanDjango)
- Fix: Cleanup and improve all Dockerfiles and significantly reduce image size (thanks FanDjango)
- Please read the Migration Guide for help migrating to the new version!
- API
- New:
EmptyDirectory
API to delete files but leave top-level directory intact (thanks FanDjango)
- New:
- FTPS
- Fix: Disable TLS 1.3 as it causes many complex networking issues during data transfer
- Fix: Unified system to handle permanent failures during
AutoConnect
- Fix: Throw
FtpProtocolUnsupportedException
if the FTP server is forcing TLS 1.3 connections - Fix: Disable SSL Buffering on control connection to improve
NOOP
handling (thanks FanDjango) - Fix: Send an additional
NOOP
command after uploading files to resolve issues (thanks FanDjango)
- FTP
- Fix: Log messages pertaining to stale data are improved (thanks FanDjango)
- New: Log the TLS protocol used after making a successful FTPS connection (thanks FanDjango)
- Fix: Correctly forward
CancellationToken
withinDownloadFile
,UploadFile
,TransferDirectory
,DeleteFile
,OpenRead
,OpenAppend
(thanks jnyrup) - Fix: Optimize
SIZE
command usage forUploadFile
inNoCheck
andOverWrite
modes (thanks FanDjango) - Fix: Allow reusing the
ActivePorts
in FTP Active connection mode (thanks FanDjango)
- Z/OS
- Proxies
- Please read the Migration Guide for help migrating to the new version!
- Special thanks to Robin Rodricks, Michael Stiemke and Jonas Nyrup for this release!
- Constructor API
- New: 4 new FTP client constructors that accept FTP host, credentials, config and logger
- Remove extraneous constructors because properties can be used instead
- Asynchronous API
- New: Split main FTP client classes into
FtpClient
andAsyncFtpClient
- New: Split main FTP client interfaces into
IFtpClient
andIAsyncFtpClient
- New: Split common FTP functionality into
BaseFtpClient
- New: Drop
Async
suffix for all async FTP methods inAsyncFtpClient
- New: Split main FTP client classes into
- Config API
- New: Remove all config settings from FtpClient and move it into
client.Config
object - New: Dedicated class to hold config settings
FtpConfig
to cleanup client API
- New: Remove all config settings from FtpClient and move it into
- Logging API
- New: Remove
client.OnLogEvent
andFtpTrace
system - New: Add logger system
client.Logger
using industry-standardILogger
interface - New: Add Nuget dependency
Microsoft.Extensions.Logging.Abstractions
v2.1.0 - Renamed: Legacy logging callback
OnLogEvent
is now renamed toLegacyLogger
- Renamed: Logging settings:
LogIP
renamed toLogHost
- Remove logging setting
LogFunctions
as it is always enabled
- New: Remove
- FTP Proxies
- New: Split FTP proxy classes into
FtpClient*Proxy
andAsyncFtpClient*Proxy
- New: FTP proxy classes moved into
FluentFTP.Proxy.SyncProxy
andFluentFTP.Proxy.AsyncProxy
NS - New: FTP proxy classes with fully async implementations
- Fix: Properly override
HandshakeAsync
in async FTP proxies (thanks jnyrup)
- New: Split FTP proxy classes into
- Organization
- Completely redesign the FTP client code organization and structure
- Update all tests and examples to use the new API and
AsyncFtpClient
- Hide all internally-used functions behind the interface
IInternalFtpClient
- Code style standardization and use new C# language constructs (thanks jnyrup)
- Add styling rules to
.editorconfig
to prevent using IDE defaults (thanks jnyrup)
- Modernization
- Drop support for .NET Standard 1.2, 1.4 and .NET 2.0, 3.5, 4.0 and 4.5
- Add support for .NET 4.6.2 and 4.7.2
- Remove conditional compilation statements for unsupported platforms
- Remove uncommon static methods
FtpClient.Connect
andFtpClient.GetPublicIP
- Remove uncommon method
DereferenceLink
andDereferenceLinkAsync
- Remove uncommon properties
QuickTransferLimit
,MaximumDereferenceCount
,EnableThreadSafeDataConnections
,PlainTextEncryption
- Remove uncommon feature
FtpListOption.DerefLinks
- Remove obsolete hashing commands
GetHashAlgorithm
,SetHashAlgorithm
,GetHash
, etc - Remove obsolete async pattern using
IAsyncResult
- Fix: Forward cancellation token in UploadDirectory and Proxy HandshakeAsync (thanks jnyrup)
- Fix: Parity in sync/async implementations of
Authenticate
(thanks FanDjango) - Fix: Improve masking out support for removing sensitive usernames from FTP logs
- Fix: Change all public fields to properties in classes:
FtpListParser
,FtpClientState
,FtpFxpSession
,FtpFxpSessionAsync
,FtpListItem
,FtpProfile
,FtpResult
- Fix: Change all public fields to properties in rules:
FtpFileExtensionRule
,FtpFileNameRegexRule
,FtpFileNameRule
,FtpFolderNameRegexRule
,FtpFolderNameRule
,FtpSizeRule
- Server support
- New: Add
SslProtocolActive
property to retrieve the negotiated SSL/TLS protocol version - Fix: z/OS: Improve server handling for absolute path calculation (thanks FanDjango)
- Fix: z/OS: Remove direct z/OS dependancy in
GetListing
(thanks FanDjango) - Fix: z/OS: Add some special cases to handle conversion of remote FTP paths (thanks FanDjango)
- Fix: z/OS: Add missing parser tests for z/OS FTP server (thanks FanDjango)
- Fix: z/OS: Fix file size calculation for non-unix z/OS files (thanks FanDjango)
- Internal: Add integration tests for
GetListingAsyncEnumerable
(thanks tommysor) - Internal: Remove 3 test dockers that do not work (thanks tommysor)
- New: Detect D-Link, TP-LINK, Huawei, MicroTik FTP servers (allows for future server-specific handling)
- Fix:
AutoConnect
now correctly handles internalAggregateException
(.NET 5.0+) - Fix:
AutoConnect
now correctly connects to servers requiring TLS 1.2 - Internal: Support automated tests for VsFtpD servers (thanks tommysor)
- Internal: Add tests for custom FTP server auto connection
- New: Add 5 missing methods into the
IFtpClient
interface - Fix: z/OS: Inconsistent implementations of
GetListing
absolute path conversion
- New:
GetListingAsyncEnumerable
method to get file listing usingIAsyncEnumerable
pattern - New: During
AutoConnect
, throwFtpProtocolUnsupportedException
if newer .NET required - Fix: Support connecting to TLS 1.3 servers using
AutoConnect
(.NET 5.0+) - Fix: Support automated tests for PureFTP and ProFTP servers (thanks tommysor)
- New:
Clone
method allows for cloning anFtpClient
connection with all settings copied - New:
InternetProtocol
property which returns the current protocol used (IPV4/IPV6) - New:
Status
property which returns the currentFtpClientState
flags (advanced use only) - Fix:
AutoConnect
/AutoConnectAsync
now correctly configure Azure FTP servers - Internal: Add integration test system using docker to test FluentFTP against many supported FTP servers
- Internal: Refactor server specific, server strings, cloning and auto connection logic into modules
- Fix:
ConnectAsync
correctly honorsConnectTimeout
andTimeoutException
is correctly thrown - Internal: Add unit tests for
Connect
/ConnectAsync
to ensureConnectTimeout
is honored - Internal: Refactor internal file listing handlers & proxy implementation (API is unchanged)
- New: Username/password authentication for SOCKS5 proxy connections
- New: Correctly fill in
ConnectionType
for all proxy types - New: Improved pattern to connect to proxy servers, all details can be specified in
FtpProxyProfile
- New: Examples for all types of proxies (
ConnectProxyHttp11
,ConnectProxySocks4
,ConnectProxySocks4a
,ConnectProxySocks5
) - Change: Rename class
SocksProxyException
toFtpProxyException
- Change: Rename class
ProxyInfo
toFtpProxyProfile
and rename members
- Change: Rename enum
FtpFileSystemObjectType
toFtpObjectType
- Change: Rename enum
FtpFileSystemObjectSubType
toFtpObjectSubType
- Change: Rename API
Upload
toUploadBytes
andUploadStream
instead of overloading - Change: Rename API
Download
toDownloadBytes
andDownloadStream
instead of overloading - Change: Logging will always mask host IP, username and password by default (configurable)
- New: Throw
AggregateException
when an error occuring during resuming a file upload (.NET 4.5+) - New: Code generation for parsed file item in order to build accurate unit tests
- New: Unit tests for Windows, Unix, OpenVMS, NonStop, IBM, Machine listing parsers
- New: Unit tests for Timezone conversion to UTC and to local time
- Fix: Improvement to directory parsing for Windows, Unix, OpenVMS, NonStop, Machine listings
- Fix: Support parsing of links and Unix-symlinks in Machine listings
- Fix: Enable 2 FTP server specific handlers
- Fix: Error when downloading large files through SOCKS4 or SOCKS4a proxy (thanks fire-lizard)
- Fix: Disable SSL Buffering in .NET 6 as it was in .NET 5
- Major: Added support for SOCKS4 proxy servers using the
FtpClientSocks4Proxy
client class (thanks fire-lizard) - Major: Added support for SOCKS4a proxy servers using the
FtpClientSocks4aProxy
client class (thanks fire-lizard)
- New: Detect Rumpus FTP servers for Mac (allows for future server-specific handling)
- New: Detect ABB IDAL FTP servers (allows for future server-specific handling)
- New: Add
DisconnectWithShutdown
property to configure shutdown signal on disconnect - Change: Rename
UngracefullDisconnect
toDisconnectWithQuit
- Fix: Resolve long timeouts after socket stream disconnected
- Fix: IOException in synchronous methods when AUTH TLS is rejected (thanks yatlor)
- New: Support for .NET 6.0
- Fix: For FileZilla FTP Server, TLS socket would be incorrectly closed (thanks michael-hoedl)
- Fix: For Windows Server IIS, the space at the beginning of the file name is excluded (thanks tYoshiyuki)
- Change: Remove
Obsolete
from allOpenRead
/OpenWrite
/OpenAppend
API as it is not planned for deletion - Fix: Calculate checksum for files with whitespaces in their name (thanks simonefil)
- Fix: z/OS:
GetListing
: Handle large file sizes reported in Used column (thanks FanDjango) - Fix: z/OS:
IsRoot
improved to handle Unix realm as well (thanks FanDjango) - Fix:
DownloadFile
correctly handles connection interruptions and resumes partially downloaded files (thanks FanDjango)
- Fix:
SetWorkingDirectoryAsync
doesn't set working directory due to missing cache invalidation (thanks FanDjango) - Fix: Handle multiline
FEAT
replies to support ProFTPD capability reporting (thanks FanDjango) - Fix: Correctly disposes
CancellationTokenSource
created duringConnectAsync
(thanks jnyrup) - Fix: Printing of error messages in some
ArgumentNullException
andArgumentOutOfRangeException
(thanks jnyrup) - Fix: Wrong file parser being selected for servers: NonStop/Tandem, OpenVMS, Windows CE, IIS (thanks jnyrup)
- Performance: Improve performance of async methods that return constant values (thanks jnyrup)
- New: Detect Titan FTP servers (allows for future server-specific handling)
- Fix: Validation of short CRC checksum fails due to mismatch of hex hash format
- Change: Remove redundant and extranous
OpenRead
/OpenWrite
/OpenAppend
API and keep only 2 methods each - Change: Mark
OpenRead
/OpenWrite
/OpenAppend
API as obsolete with warnings and recommend high level API - Change: Cleanup dependencies for netstandard2.0, netstandard2.1 and net5.0 targets (thanks jnyrup)
- Change: Restore the older
OpenRead
API to prevent breaking older projects that depend on it (thanks FanDjango)
- New:
GetZOSFileSize
is now removed and superceeded byGetFileSize
which handles z/OS servers - New: Refactor and cleanup z/OS specific logic for: post-connect init,
IsRoot
,GetFileSize
- Change:
OpenRead
API no longer supportscheckIfFileExists
argument (thanks FanDjango) - Fix: z/OS & ASCII transfers: Don't get filesize if filesize already known during downloading (thanks FanDjango)
- Fix: z/OS
UploadFilesAsync
: Fixed IBM MVS File uploading path calculation (thanks FanDjango) - Fix: Close underlying FTP socket connection on async cancellation on .NET Core (thanks datvm)
- Fix: Correctly handle FTP connection timeout on .NET Core (thanks datvm)
- Fix: Enable detection of IBM OS/400 servers that were disabled during server-specific handling
- New: Detect PyFtpdLib FTP servers (allows for future server-specific handling)
- Fix: Pass CancellationToken to all methods that support cancellation (thanks 0xced)
- Fix: Error check on z/OS init commands to ensure they executed correctly (thanks FanDjango)
- Fix: Improve
FileExists
for z/OS: better no SIZE, no MDTM on non HFS files (thanks FanDjango) - Fix:
DownloadFile
for z/OS:SetDataType
directly before theRETR
command (thanks FanDjango) - Fix:
IsAuthenticated
is not updated when callingConnectAsync
(thanks datvm) - Fix: Reduce number of times
SetDataType
is called internally to improve performance (thanks FanDjango) - Fix: Fail to detect z/OS server if
Unix
is also mentioned in welcome message (thanks FanDjango)
- Fix: z/OS GetFileSize: Ignore SIZE capability even if advertised by server as pointless (thanks FanDjango)
- Fix: z/OS DownloadFile: Read to end of stream because filesize is always inaccurate (thanks FanDjango)
- Fix: z/OS DownloadFile: Fix check for infinity or NaN progress values (thanks FanDjango)
- Fix: z/OS GetListing: Path can be null causing an exception (thanks FanDjango)
- Fix: z/OS GetListing: Large files overflow on size calculation resulting in negative file sizes (thanks FanDjango)
- Fix: z/OS GetListing: Listing fails unless users
CWD
to the correct folder of a non-RECFM=U
PDS (thanks FanDjango)
- New: Support for connecting to FTP/FTPS servers via a SOCKS5 proxy (thanks bjth)
- New: Autoconfigure IBM z/OS FTP server using
SITE DATASETMODE
andQUOTESOVERRIDE
(thanks FanDjango) - Fix:
GetListing
itemFullname
is now correctly calculated for Unix and z/OS systems (thanks FanDjango)
- New:
GetZOSFileSize
APIs to get file size of IBM z/OS file system objects (thanks FanDjango) - New:
GetZOSListRealm
APIs to get realm of IBM z/OS servers (thanks FanDjango) - New: Enhance the z/OS listing parser to get LRECL (via XDSS) on behalf of user (thanks FanDjango)
- Fix:
AutoConnect
detects rejected certificates on connection and raisesFtpInvalidCertificateException
(thanks FanDjango) - Fix:
FtpListOption.ForceList
is not being honored by GetListing and machine listings are used instead (thanks FanDjango) - Fix:
GetListing
regression causing many untrue parse fail warnings (thanks FanDjango) - Fix:
GetObjectInfo
is overwriting Modified date of aFtpListItem
if the consecutive MDTM command fails (thanks Dylan-DutchAndBold) - Fix: reusing same FtpClient should reload server capabilities unless its a cloned connection (thanks FanDjango)
- Fix: Executing
CWD
usingExecute
API does not invalidate internal CWD cache (thanks FanDjango)
- Fix:
UploadFile
fails to upload inFtpRemoteExists.Resume
mode even if stream is seekable
- Fix:
AutoConnect
loads the newly detectedFtpProfile
to update properties & encryption - Fix: Passive connections work in
FtpEncryptionMode.Auto
mode and FTPS connection fails
- Fix:
AutoDetect
correctly recommendsFtpEncryptionMode.None
if FTPS connection failed - Fix:
AutoDetect
crashes because attempting to read socket type after disconnected
- Major:
AutoDetect
does not cycle through data connection types during connection as it is irrelevant - Major:
AutoDetect
calculates a data connection type after connection succeeds (EPSV or PASV)
- Fix:
ConnectAsync
now correctly creates a FTP server-specific handler to matchConnect
behaviour
-
Automatic connection
- Major:
AutoConnect
takes far fewer connection attempts due to improvements in connection handling - Major:
AutoConnect
andAutoDetect
are much faster and smarter and only try each setting once if possible - Major:
AutoDetect
only tries Explicit and Implicit FTPS once and then falls back to plaintext FTP - Major:
AutoDetect
only tries UTF-8 and never ASCII because most UTF-8 servers don't advertise it - New:
AutoDetect
verifies if the server supports UTF-8 and updates theFtpProfile
accordingly - New:
FtpProfile
code generation adds a warning message if the encoding mode is unverified - New:
AutoConnectAsync
now uses true asynchronous connection backed by newAutoDetectAsync
- New:
AutoConnect
now auto computes an FTP port unless a non-standard port is already set - New:
AutoConnect
uses the mainFtpClient
connection rather than creating one clone per attempt - Fix:
AutoConnect
remains connected to the first working profile rather than connecting twice on success - Fix:
AutoConnect
reuses the same connection for FTPS and FTP rather than connecting again - Fix: Ensure FTP server capabilities are loaded during
AutoDetect
if original connection is blank - Fix:
AutoConnect
andAutoDetect
will now throw exceptions for permanent failures (bad host/credentials) - Fix:
ConnectAsync
now correctly resets the state flags to matchConnect
behaviour - Fix:
Port
now correctly calculates the default port 21 when usingFtpEncryptionMode.Auto
- Major:
-
Appending and resuming uploads
- Major: The setting
FtpLocalExists.Append
is now renamed toFtpLocalExists.Resume
- Major: The setting
FtpRemoteExists.Append
is now renamed toFtpRemoteExists.Resume
- Major: Split
FtpRemoteExists.Append
into two properties with distinct behaviour (Resume
andAddToEnd
) - Major: Improvements to
UploadFile
andUploadFileAsync
to support appending and resuming of uploads - Major:
UploadFile
always sets the length of the remote file stream before uploading, appending or resuming - Major:
UploadFile
skips uploading inResume
mode if local and remote file are equal length - Fix: Implementation for resuming uploads using
UploadFile
based on fixes inUploadFileAsync
- Major: The setting
-
Machine listings
- Major:
GetListing
prefers using Machine Listings over LIST command, unless a custom list parser is set - Fix:
ListingParser
property is updated according to auto-detected parser duringConnect
andConnectAsync
- Fix:
DeleteDirectory
andDereferenceLink
methods no longer useForceList
and so prefer using Machine Listings
- Major:
-
File hashing
- Major: All low-level hash methods are now inaccessible and
GetChecksum
is the only recommended approach - Fix:
GetChecksum
now prints function call logs and sanitizes the input path - New:
GetChecksum
switches to the first preferred hash algorithm forHASH
command if no algorithm is specified - New:
GetChecksum
validates if the required algorithm is unsupported and throwsFtpHashUnsupportedException
- New:
GetChecksum
validates if hashing is unsupported by the server and throwsFtpHashUnsupportedException
- Fix:
GetChecksumAsync
now takes the cancellation token last to follow conventions (argument reorder) - Fix: Improved extraction of hash checksum when using the HASH command
- Fix: Improved extraction of hash checksum when using the MD5, SHA1, SHA256, SHA512 or X-series commands
- New:
SetHashAlgorithm
now only modifies the hash algorithm if it has changed
- Major: All low-level hash methods are now inaccessible and
-
Path sanitization
- Fix: All high level API methods sanitize input paths to improve robustness
- Fix:
GetWorkingDirectory
always sanitizes the returned working path directory - Fix: Correctly handle server-specific absolute FTP paths for async operations
- Fix: All function call logs now print the sanitized path rather than raw input path
-
Path improvements
- Major:
GetWorkingDirectory
is now extremely fast and caches the working dir path for subsequent calls - Fix:
FileExists
supports checking name listings for Windows NT servers which use invalid slashes - Fix: Root directory FTP paths no longer return
./
and instead return/
- Major:
-
Other improvements
- Major: All legacy asynchronous methods using
IAsyncResult
pattern have been removed (outdated since 2012) - Fix: FXP file transfers for glFTPd server always try PASV and CPSV commands to get passive port
- Fix: Add logging for skipped files in
UploadFile
- Fix: Add file path details in skipped files logged by
UploadFile
andDownloadFile
- New:
GetNameListing
to print results of name listing as verbose logs, similar toGetListing
- New:
GetFileSize
andGetFileSizeAsync
to support a configurable return value if the file does not exist - New:
FtpFolderNameRule
now supportsstartSegment
to skip checking root directory folder names - New:
FtpFolderNameRegexRule
now supportsstartSegment
to skip checking root directory folder names
- Major: All legacy asynchronous methods using
- New: Add support for
IsAuthenticated
property which enables detection of FTP connection and authentication - Fix: Improved file path calculation when uploading files to IBM zOS running MVS (thanks arafuls)
- Fix: Detection of file exists for Windows NT Servers fails due to invalid slashes
- Fix: Ensure
CompletionCode
is always null-checked to fix edge cases and comply with existing implementation - Fix: Possible wrong IP when connecting to Azure FTP Server using
EPSV
command (thanks jsantos74)
- Fix file path calculation when uploading files to IBM zOS running MVS (thanks arafuls)
- Detect fully-qualified directory when using data sets on IBM zOS running MVS (thanks arafuls)
- Major: Refactor and cleanup helpers & extension methods
- Major: Changed namespace of
FtpTrace
toFluentFTP.Helpers
- Major: Changed namespace of
FtpListParser
toFluentFTP.Helpers
- Major: You need to import
FluentFTP.Helpers
to gain access to FTP extension methods - Major: Changed visibility of various internal FTP helpers to
internal
to prevent external access - New: Ability to set a local IP address to be used for FTP connections (thanks daviddenis-stx)
- New: Properties for local IP:
SocketLocalIp
,SocketLocalEndPoint
,SocketRemoteEndPoint
(thanks daviddenis-stx)
- New: Ability to block certain server ports from being used during passive FTP connection (PASV/EPSV)
- New:
PassiveBlockedPorts
andPassiveMaxAttempts
properties to configure passive blocked ports
- Fix: Add support for another server specific string to detect if file exists
- Fix: Prevent memory leaks with FTPS on AKS by disabling
ValidateCertificateRevocation
by default
- Fix:
DownloadFile
should fail if directory path is passed inlocalPath
- Fix:
LastReply
is not set when using async methods - Fix: Ambiguous call when using LINQ extension methods and EF core
- Fix: Remove dependency on
System.Linq.Async
and disableGetListingAsyncEnumerable
- Fix: Use .NET Core API for .NET 5 builds to fix various networking and connectivity issues
- New: Support detection of FRITZ!Box FTP servers (allows for server specific commands)
- Fix: Do not force users to
Connect
if capabilities are not loaded (only force ifCapabilities
are read before connecting)
- Fix: Conditionally hard-abort
AutoConnect
only if the credentials were incorrect
- New:
LogToFile
andLogToConsole
are now available on .NET Framework / .NET 5.0 - Fix:
Capabilities
&HashAlgorithms
are returned if they are loaded regardless of connection status
- Fix: Prevent
Capabilities
&HashAlgorithms
from causing sync-over-async path - Fix:
NullReferenceException
duringUploadFile
if the error message is unknown - Fix: If incorrect credentials are passed to
AutoConnect
, it does not hard abort - Fix: Initializing TLS Authentication hangs in .NET 5 if
SslBuffering
is enabled
- New: Support for .NET 5.0 platform
- New: Support for
IAsyncEnumerable
pattern in .NET Standard 2.0+ and .NET 5.0 (thanks hez2010) - New: Async variant of
GetListingAsync
introduced:GetListingAsyncEnumerable
- Fix: URI ports not being respected when Uri constructor used (thanks julian94)
- Fix: Respect
332 Need account for login
response during FTP client authorization (thanks novak-as) - Fix: Set default value for
restartPosition
inDownload
method to matchFtpClient
method (thanks AdamLewisGMSL) - Fix: Improved handling for resuming upload when the connection drops (thanks pradu71)
- Fix: Honor custom parsers if server-specific handler is used
- Fix: Create server-specific handler if a custom handler has not been set (thanks Adhara3)
- New: Reworked timezone conversion API (simply set
TimeConversion
andTimeZone
) - New: Options to convert server timestamps into the format of your choice (
ServerTime
,LocalTime
andUTC
) - New: Support for conversion to local timezone in .NET core (set
LocalTimeZone
) - New:
GetListing
honors the time conversion settings of the active client - New:
GetModifiedDate
honors the time conversion settings of the active client - New:
SetModifiedDate
honors the time conversion settings of the active client - New: Reworked API for Custom file listing parsers (simply set
ListingCustomParser
on the client) - Fix: Drop support for legacy file listing parsing routines (
FtpParser.Legacy
will no longer work) - Fix: Unexpected time conversion occuring in
GetModifiedTimeAsync
- Change: Breaking changes to the
TimeConversion
property. - Change: Breaking changes to the
TimeOffset
property, which has been replaced byTimeZone
- Fix: "The connection was terminated before a greeting could be read"
- Platform: Add support for .NET Standard 2.1
- Platform: Upgrade
System.Net.Security
from version 4.3.0 to 4.3.2 to fix security issues - Performance: Quickly abort detection if host is unavailable during
AutoDetect
/AutoConnect
- Fix:
UploadDirectory
fails for some files with "Unable to read data from the transport connection" (thanks manuelxmarquez) - Fix: Comment for
UploadFile
/UploadFileAsync
/DownloadFile
/DownloadFileAsync
methods - Fix: Stack overflow during connection when server responds incorrectly to PASS command
- Fix: Uncatchable NullReferenceException is occasionally thrown from
ConnectAsync
- New: Automatic FTPS connection mode:
FtpEncryptionMode.Auto
which connects in FTP and attempts to upgrade to FTPS - New:
IsEncrypted
property to check if FTPS encryption is currently active for this connection - Fix:
ValidateCertificateRevocation
property was not being honored in async version (thanks kolorotur)
- Fix: Ensure file is retried sucessfully when first upload/download fails with an
IOException
(thanks manuelxmarquez) - Fix: Ensure file streams read and write correctly even when no
FtpClient
is provided (thanks manuelxmarquez) - Fix: Clear custom parser when removing parser or clearing all parsers (thanks rubenhuisman)
- New:
LocalFileBufferSize
property to control size of file buffer during local file I/O
- New:
UploadDirectoryDeleteExcluded
property to control if excluded files are deleted during Upload (thanks philippjenni) - New:
DownloadDirectoryDeleteExcluded
property to control if excluded files are deleted during Download (thanks philippjenni) - Fix: Dispose AsyncWaitHandles to stop handle leak in .NET Framework 4.5 (thanks sdiaman1)
- Fix: Implement proper cancellation support in
UploadDirectory
(once file transfer begins it cannot be cancelled) - Fix: Implement proper cancellation support in
DownloadDirectory
(once file transfer begins it cannot be cancelled) - Fix: Implement proper cancellation support in FXP
TransferDirectory
- Fix: Implement proper cancellation support in recursive
GetListing
- Fix: Correctly resume when unexpectedEOF error received during uploading a file (thanks mrcopperbeard)
- Fix: Hide internal properties in
FtpClient
that are not meant to be exposed - Fix: Update
IFtpClient
with the latest set of public properties that are meant to be exposed
- Fix: Downloading or uploading a directory can generate incorrect local paths
- Fix: Downloading or uploading a directory can generate incorrect local paths
- Fix: Expose
LoadProfile
API so it can be called by the generated code fromAutoDetect
- New:
ListingDataType
property to get file listings in ASCII/Binary - New:
DownloadZeroByteFiles
property to control if zero-byte files should be downloaded or skipped - Fix: Downloading 0-byte files crashes since no data downloaded
- New: All server-specific handlers moved to dedicated classes that extend
FtpBaseServer
- New: Ability to handle custom non-standard FTP servers by extending
FtpBaseServer
- Fix: Only overwrite local file after the first bytes downloaded of a remote file
- New: Tracking progress with FXP transfers is supported for all transfer modes
- New: Track low-level progress with new
TransferredBytes
inFtpProgress
class (thanks Adhara3) - New:
FXPProgressInterval
property to control how often FXP progress reports are sent - Fix: Hide
TransferFileFXPInternal
because its an internal transfer method and not to be used directly
- Fix:
FtpFileExtensionRule
was failing to compare extensions unless they were prefixed with a dot
- New:
GetChecksum
allows you to specify a hash algorithm to be run on the server if supported - New:
GetChecksum
has special support for switching the server-side algorithm for HASH command support - New: FXP file transfer now validates the file using the first mutually supported algorithm
- Fix: Incorrectly formatted string returned by utility method
TransferSpeedToString
- New:
CompareFile
andCompareFileAsync
methods to quickly perform various equality checks on a uploaded/downloaded file
- Fix: When download fails and we need to retry on failed verification, ensure that file is re-downloaded
- Fix: When FXP transfer fails and we need to retry on failed verification, ensure that file is re-transfered
- Fix: When uploaded file is skipped,
FtpStatus.Failed
is returned instead ofFtpStatus.Skipped
- Fix: Properly handle 4xx and 5xx series of errors and indicate failure when uploading or downloading files
- Fix: Correctly detect if server-side recursion is supported otherwise fallback to manual directory recursion
- Fix: Only resume download of files if Append mode is selected (in Overwrite mode we restart the download)
- Change:
Upload
andUploadAsync
now returnsFtpStatus
to indicate skipped, success or failed
- Fix: Proper session handling for FXP connections and disconnection of cloned connections
- Performance: Reduce redundant file size check in
DownloadFile
when appending is used
- New:
AutoDetect
andAutoConnect
now auto-configure for Azure FTP servers using known connection settings - Improve code generation of
FtpProfile
to use LoadProfile rather than setting each property individually - Add advanced Timeout and Socket settings to
FtpProfile
for Azure auto configuration - Fix: All exception classes now inherit from
FtpException
- All exceptions and
FtpProfile
are now serializable in .NET Framework
- New:
TransferFile
andTransferDirectory
methods to transfer files from server to server (thanks n0ix) - New: FXP (File Transfer Protocol) implementation to support direct server-to-server transfers (thanks n0ix)
- New: Predefined rules for filtering on file name using regular expressions (thanks n0ix)
- New: Predefined rules for filtering on folder name using regular expressions (thanks n0ix)
- Fix: Don't calculate ETA and percentage of
FtpProgress
if file size is zero (thanks Adhara3) - Fix:
GetFilePermissions
should useGetObjectInfo
instead ofGetListing
to prevent incorrect filepaths
- New: Support for MMD5 file hashing command to validate downloaded/uploaded files. (thanks n0ix)
- Change: Disable all
Begin*
andEnd*
methods for .NET 4.5 and onwards asasync
/await
is supported. - Improve:
GetHashAlgorithmAsync
andSetHashAlgorithmAsync
implemented as true async methods with cancellation support - Improve:
GetObjectInfoAsync
implemented as true async methods with cancellation support
- New: Download and upload file methods indicate if file was transferred, skipped or failed to transfer
- New: C# and VB.NET Examples for all file and folder transfer methods
- New: VB.NET Examples for all methods (not included in Nuget package but available on Github)
- Change:
DownloadFile
andUploadFile
returnFtpStatus
instead of boolean flag for tri-state feedback
- New: Support for XCRC FTP Command and CRC32 hash support to validate downloaded/uploaded files (thanks n0ix)
- Fix: Calculation of local file path during DownloadFolder sometimes ignores base directory
- New: Support multi-file progress tracking by indicating file index and local & remote path of the file
- New:
UploadDirectory
andDownloadDirectory
now supports tracking progress of the entire task - New:
UploadFiles
andDownloadFiles
now supports tracking progress for both sync/async methods - Fix: Update
IFtpClient
interface by adding newUploadDirectory
andDownloadDirectory
methods - Fix: Correctly determine file exists on servers that don't support SIZE command and return error 550
- Fix: Support more strings to determine if file exists using SIZE command
- New:
UploadDirectory
andUploadDirectoryAsync
methods to recursively upload or mirror a directory - New:
DownloadDirectory
andDownloadDirectoryAsync
methods to recursively download or mirror a directory - New: Rule engine to filter files that should be uploaded/downloaded according to multiple user-defined rules
- New: Predefined rules for filtering on folder name, useful for blacklisting certain system folders
- New: Predefined rules for filtering on file name or file extensions, useful for transferring a subset of files
- New: Predefined rules for filtering on file size, useful for filtering out very large files
- New: Ability to determine parent/self/child directories in listing using
SubType
property ofFtpListItem
- Fix: Machine listings sometimes cause infinite recursion in
GetListing
when recursing into self directory - Change:
CreateDirectory
andCreateDirectoryAsync
now return a flag indicating if it was created or skipped - Change: Use public fields instead of public properties for
FtpListItem
- Change: Improve performance of
CreateDirectory
by skipping the directory exists check
- Fix: Detect "file size not allowed in ASCII" string for French FTP servers
- Fix: TimeoutException when trying to read FTP server reply after Download/Upload
- New: Add
SendHost
andSendHostDomain
to control if HOST command is sent after handshake (thanks dansharpe83)
- Fix: Read stale NOOP responses after file transfer and also after
226 Transfer complete
(thanks aliquid) - Fix: Correct default value for
TimeConversion
property to assume UTC timestamps
- New: Support .NET Standard 2.0
- New: Keep control socket alive during long file transfers using NOOP (thanks aliquid)
- New: Add
NoopInterval
property to control interval of NOOP commands (thanks aliquid) - New: Add
TimeConversion
property to control if timestamps are converted from UTC into local time - Refactor: Rename
FtpExists
toFtpRemoteExists
to make its usage clear - New: Support detection of IBM z/OS and MVS FTP OS and server (allows for server specific commands)
- New: New constructors for
FtpClient
to support hostnames inUri
format - Fix: Always send progress reports after file download, even for zero-length files
- New:
ValidateCertificateRevocation
property to control if certificate revocation is checked.
- New:
ValidateAnyCertificate
property to validate any received server certificate, useful for Powershell - Fix: Default SSL protocol used in .NET 4.5+ release is now TLS 1.2 (latest supported protocol)
- New: Override the server-specific recursive LIST detection by setting
RecursiveList
- Fix typo in IP parsing regex that causes fallback to Host IP to fail (thanks Andy Whitfield)
- Fix: Verification of the MD5 Hash when file name contains spaces (thanks Nimelo)
- Fix: Safely absorb TimeoutException thrown after the file has fully uploaded/downloaded
- New: Progress reporting for synchronous methods
Upload
,Download
,UploadFile
andDownloadFile
are now sent via delegates - Fix: Correctly send progress for synchronous methods and retain
IProgress
for async methods
- Fix: Correctly assume Unix file listing parser for SunOS & Solaris servers
- Fix: Safely absorb TimeoutException thrown after the file has fully uploaded/downloaded
- New: Support detection of Sun OS Solaris FTP OS and server (allows for server specific commands)
- Fix: UploadFile fails when destination folder is empty on SunOS (550 error)
- Fix: Unable to upload files to OpenVMS servers if path contains numeric characters
- Fix: Assume FTP commands supported by OpenVMS HGFTP server if FEAT not supported
- FiX: Improve detection of OpenVMS absolute paths
- Fix:
Connect
&ConnectAsync
throw ArgumentException when passing an incompleteFtpProfile
- New: Auto-detect the correct FTP listing parser when SYST command fails (IIS, Azure, OpenVMS)
- New: Assume FTP commands supported by OpenVMS HGFTP server
- FiX: Support edge case for OpenVMS absolute paths (directive can be alpha-numeric)
- New: Improved transfer rate throttling when using an upload/download speed limit (thanks wakabayashik)
- New: Support detection of XLight FTP server software (allows for server specific commands)
- New: Partial support for getting directory listing using STAT command (
GetListing
supports newFtpListOption.UseStat
) - Fix:
GetFileSize
always returns 0 instead of correct file size (thanks RadiatorTwo)
- Fix:
FileExists
andFileExistsAsync
support switching to binary mode for servers that need it
- Fix: Error using BlueCoat proxy to an FTP server on a port other than port 21
- Fix: Error using UserAtHost proxy to an FTP server on a port other than port 21
- New: Change
Capability
API to return a list instead of bitwise enum (to support more than 32 distinct capabilities) - New: Change custom parsers to take capabilities as a list instead of bitwise enum (to match client implementation)
- New: Support detection of FTP2S3 gateway server software (allows for server specific commands)
- New: Support detection of server-specific capabilities of Serv-U FTP Gateway
- New: Support
RMDA
command to quickly and recursively delete a directory from Serv-U FTP Gateway
- Fix: Improve performance of
GetFileSize
to only switch to Binary for servers that require it - Fix: Ensure data type (ASCII/Binary) is correctly set during
GetFileSize
for servers that require it - Fix: Ensure data type (ASCII/Binary) is correctly set for cloned connections
- Fix: Ensure data type (ASCII/Binary) is correctly set during
GetListing
andGetNameListing
- Fix: Reset server detection state flags whenever we connect to a server, to allow for reuse of
FtpClient
- Fix: Copy server detection state flags to cloned connections to improve performance
- Fix: Retry
GetListing
if temporary error "Received an unexpected EOF or 0 bytes from the transport stream"
- Fix: Prefer using Passive/Active modes rather than Enhanced Active/Passive during auto-detection
- Fix: Some FTP servers do not open a port when listing an empty folder with
GetNameListing
- Fix: Hard catch and suppress all exceptions during disposing to solve all random exceptions
- New: Automatic FTP connection negotiation using
AutoConnect()
- New: Automatic detection of working FTP connection settings using
AutoDetect()
- New: C# code generation of working connection settings using
FtpProfile.ToCode()
- New: Support more capability detection commands: EPSV, CPSV, NOOP, CLNT, SSCN, SITE commands for ProFTPd
- New: Improve transfer performance by only attempting EPSV once and then never using it again for that connection
- New: Support MKDIR & RMDIR commands specially for ProFTPd to quickly create and delete a directory on the server-side
- New: Support PRET command before downloading or uploading files for servers like ProFTPd & DrFTPd
- New: Support detection of BFTPd server software (allows for server specific commands)
- Fix: When uploading files in
FtpExists.NoCheck
mode, file size check should not be done - Fix: Some FTP servers do not open a port when listing an empty folder (thanks Mortens4444)
- Fix:
OpenRead
withEnableThreadSafeDataConnections
always transfers in ASCII (thanks ts678) - Refactor: Delete legacy static methods:
OpenRead
,OpenWrite
,OpenAppend
(dynamic versions still exist) - Refactor: Move
CalcChmod
fromFtpClient
toFtpExtensions
(as part of repository cleanup task)
- Fix: Async methods do not work with Active FTP mode and SSL/encryption (thanks Mortens4444)
- Fix: For OpenVMS absolute paths may not contain slashes but are still absolute (3rd revision)
- Fix: Divide-by-zero exceptions while calculating progress of file uploads/downloads
- Fix: Supress all exceptions when Disposing the underlying FtpSocketStream
- Fix: Received an unexpected EOF or 0 bytes from the transport stream (thanks mikemeinz)
- Fix:
UploadFile()
progress callback is not called if the file already exists on the server - (.NET core) Fix:
Connect()
method sometimes causes the thread to hang indefinitely (thanks radiy) - Fix: Regression of #288 where upload hangs with only a few bytes left (thanks cw-andrews)
- New:
FtpAuthenticationException
for authentication errors (thanks erik-wramner) - New: Added support to detect Homegate FTP Server
- New: SSL Buffering is now switchable via the
SslBuffering
parameter - Fix: SSL Buffering is automatically disabled when using FTP proxies, and enabled in all other cases
- Fix: Revert PR #383 as it was causing regression issues in SSL connectivity
- Fix: Disable automatic IP correction to fix connectivity issues via BlueCoat proxy servers (thanks CMIGIT)
- Refactor: Rename
FtpClientUserAtHostProxyBlueCoat
toFtpClientBlueCoatProxy
- Fix: For OpenVMS absolute paths may not contain slashes but are still absolute (2nd revision) (thanks tonyhawe)
- Fix: Detect file existence string
"Can't find file"
to fix FileExists check on some servers (thanks reureu) - Fix: Feature parity between
FileExists
andFileExistsAsync
methods, added support for FtpReply 550 check (thanks reureu) - Fix: Feature parity between
UploadFile
andUploadFileAsync
methods, added support for AppendNoCheck handling (thanks reureu)
- New: Get detailed progress information for uploads/downloads via the
FtpProgress
object (thanks n0ix) - New: Get transfer speed and ETA (estimated time of arrival) for uploads/downloads (thanks n0ix)
- Fix: Files were uploaded in Write mode instead of Append mode when the exists mode is
AppendNoCheck
and we couldn't read the offset position (thanks @everbalovas) - Fix: Swap
SslStream
andBufferedStream
so proxied connections withFtpClientHttp11Proxy
are to connect (thanks @rmja)
- New: Additional FTP Server software detection (HP NonStop/Tandem, GlobalScape EFT, Serv-U, Cerberus, CrushFTP, glFTPd)
- New: Assume capabilities for servers that don't support FEAT (wuFTPd)
- Fix:
FileExists
returns false if name listing is used and server lists filenames with the path - Fix: For OpenVMS absolute paths may not contain slashes but are still absolute
- Fix: For
Download()
methodsrestartPosition
should not be mandatory
- New: Ability to cancel all async methods via
CancellationToken
(thanks WolfspiritM) - New:
ReadTimeout
is now honored by all async methods (thanks WolfspiritM) - New: FTP Server operating system detection (Windows, Unix, VMS, IBM/OS400)
- (.NET core) Fix: GetListing blocking with no timeout (thanks WolfspiritM)
- (.NET core) Fix async methods by not using the the async read function (thanks WolfspiritM)
- New: Ability to resume a download via
existsMode
onDownloadFile()
andDownloadFiles()
(thanks n0ix) - New: Ability to turn off checking for server capabilities using FEAT command (thanks nhh-softwarehuset)
- Fix: Add workaround if a server advertises a non-routeable IP in PASV Mode (thanks n0ix)
- Fix: Recursive directory deletion tries to delete the same file twice (because GetListing is also recursive)
- New:
OnLogEvent
callback to get logs in the context of indivivdual FtpClient connections - Fix: All logging is done in the context of an
FtpClient
and then passed toFtpTrace
listeners - Signature for custom list parsers has changed,
FtpClient
argument added to the end
- New: FTP Server software detection (PureFTPd, VsFTPd, ProFTPD, FileZilla, OpenVMS, WindowsCE, WuFTPd)
- New: Detect if the FTP server supports recursive file listing (LIST -R) command using whitelist
- New:
GetListing
will manually recurse through directories ifFtpListOption.Recursive
is set and server does not support recursion - New: Added
LastReply
property which returns the lastFtpReply
recieved from the server. - New: Added new upload option
AppendNoCheck
to append to a file on the server without checking if it exists (thanks @everbalovas) - Fix: During upload, respond to any error in 5xx series, not just 550 (thanks stengnath)
- Fix: Various fixes to
UploadFileAsync
based on fixes already implemented inUploadFile
- Fix:
UploadFilesAsync
witherrorHandling
deletes the entire directory instead of specific files - Fix: Server responds to EPSV with 425 "Data connection failed" but connects with PASV (thanks ejohnsonTKTNET)
- Fix: Use proper async configuration for .NET Async methods (thanks ejohnsonTKTNET)
- Fix: Improve implementation of upload and download resuming in Async methods (thanks ejohnsonTKTNET)
- Fix:
UploadFile()
orUploadFiles()
sometimes fails to create the remote directory if it doesn't exist - Fix:
DownloadDataType
Binary value ignored on ASCII-configured FTP servers - Performance improvement: Added
BufferedStream
betweenSslStream
andNetworkStream
(thanks stengnath) - Fix: When the FTP server sends 550, transfer is received but not confirmed (thanks stengnath)
- Fix: Make
Dispose
method ofFTPClient
virtual (thanks @martinbu) - Fix:
OpenPassiveDataStream
/Async()
uses the target FTP host instead of the configured proxy (thanks @rmja) - Fix:
FileExists()
for Xlight FTP Server (thanks @oldpepper) - Fix: FTPD "550 No files found" when folder exists but is empty, only in PASV mode (thanks stengnath)
- Fix: Many unexpected EOF for remote file
IOException
on Android (thanks @jersiovic) - Fix: Race condition when
BeginInvoke
calls the callback before theIAsyncResult
is added (thanks stengnath)
- Fix: Prevent socket poll from hammering the server multiple times per second
- Fix: Allow using absolute paths that include drive letters (Windows servers)
- Performance improvement: Only change the FTP data type if different from required type
- Performance improvement: Download all files in EOF mode and skip the file size check, unless download progress is required
- Added all missing async versions of FTP methods to
IFtpClient
- System: Certain core FTP socket handling operations have been changed to improve reliability & performance.
- Fix: Fix hang in TLS activation because no timeout is set on the underlying
NetworkStream
(thanks @iamjay)
- Added async versions of FTP methods to
IFtpClient
(thanks @peterfortuin) - Fix: Fixes when
ActivePorts
is specified in active FTP mode (thanks @ToniMontana) - Fix: Throw
OperationCanceledException
instead ofFtpException
when cancellation is requested (thanks taoyouh)
- Fix: Add support for checking if file exists on Serv-U FTP Server
- Fix: Make
IFtpClient
inherit fromIDisposable
(thanks @repl-andrew-ovens) - (UWP) Fix: UWP does not allow
File.Exists()
to run in UI thread (thanks taoyouh)
- Fix: When downloading files in ASCII mode, file length is unreliable therefore we read until EOF
- Fix: When upload/download progress is indeterminate, send -1 instead of NaN or Infinity
- Fix:
NetStream
was not assigned inFtpSocketStream
for .NET Standard in active FTP mode (thanks @ralftar) - Fix:
CurrentDataType
was not set for ASCII transfers inDownloadFileAsync
/UploadFileAsync
(thanks taoyouh) - Fix: Sometimes
FtpSocketStream
andFtpDataStream
are not disposed inFtpSocketStream.Dispose
(thanks taoyouh)
- New Progress reporting for
UploadFile
&DownloadFile
methods viaIProgress
- Fix:
Stream.Position
should not be set inUploadFileInternal
unless supported
- New Task-based async methods for .NET Standard and .NET Fx 4.5 (thanks taoyouh)
- New async methods for
UploadFile
,DownloadFile
,UploadFiles
&DownloadFiles
(thanks artiomchi) - (UWP) Fix:
FileNotFoundException
with referenceSystem.Console
(thanks artiomchi) - (.NET core) Fix: Thread suspends when calling
UploadFile
orDownloadFile
(thanks artiomchi) - (.NET core) Fix: File download hangs inconsistently when reading data from stream (thanks @artiomchi, bgroenks96)
- (.NET core) Fix: Stream does not dispose due to wrong handling of closing/disposing (thanks artiomchi)
- Fix: File upload EOS bug when calling
Stream.Read
(thanks bgroenks96, @artiomchi, @taoyouh) - Fix:
DownloadFileInternal
not recognizing the download data type withEnableThreadSafeConnections
(thanks bgroenks96) - (Backend) Migrate to a single VS 2017 solution for all frameworks (thanks artiomchi)
- (Backend) Continuous Integration using AppVeyor (thanks artiomchi)
- Add
IFtpClient
interface to build unit tests upon mainFtpClient
class (thanks Kris0) - Disposing
FtpDataStream
reads server reply and closes the underlying stream (thanks Lukazoid)
- New
SetModifiedTime
API to change modified date of a server file in local timezone/UTC - Add type argument to
GetModifiedTime
, allowing for getting dates in UTC/Local timezone - Breaking changes to Async API of
GetModifiedTime
(addition of type argument) GetModifiedTime
andSetModifiedTime
now honor theTimeOffset
property inFtpClient
- Add
checkIfFileExists
toOpenRead
,OpenAppend
andOpenWrite
to skipGetFileSize
check - Fix issue where
InnerException
is null during a file transfer (upload/download) - Improve performance of typical uploads/downloads by skipping the extra file exists check
- Fix for
CreateDirectory
andDirectoryExists
to allow null/blank input path values - Fix for
GetFtpDirectoryName
to return correct parent folder of simple folder paths (thanks ww898)
- Add argument validation for missing/blank arguments in :
Upload, Download, UploadFile(s), DownloadFile(s), GetObjectInfo, DeleteFile, DeleteDirectory, FileExists, DirectoryExists, CreateDirectory, Rename, MoveFile, MoveDirectory, SetFilePermissions, Chmod, GetFilePermissions, GetChmod, GetFileSize, GetModifiedTime, VerifyTransfer, OpenRead, OpenWrite, OpenAppend
- Disable all async methods on .NET core due to persistant
PlatformUnsupported
exception (if you need async you are free to contribute a non-blocking version of the methods)
- Increase performance of
GetListing
by reading multiple lines at once (BulkListing property, thanks sierrodc)
- Add support for parsing AS400 listings inside a file (5 fields) (thanks rharrisxtheta)
- Retry interpreting file listings after encountered invalid date format (thanks rharrisxtheta)
- Always switch into binary mode when running SIZE command (thanks rharrisxtheta)
- Honor
UploadDataType
andDownloadDataType
in all sync/async cases (thanks rharrisxtheta) - Force file transfers in BINARY mode for known 0 byte files (thanks rharrisxtheta)
- Allow file transfers in ASCII mode if the server doesn't support the SIZE command (thanks rharrisxtheta)
- Fix
NullReferenceException
when arguments are null duringFtpTrace.WriteFunc
- Remove internal locking for .NET Standard 1.4 version since unsupported on UWP
- Remove dependency on
System.Threading.Thread
for .NET Standard 1.4 version (for UWP)
- Allow transferring files in ASCII/Binary mode with the high-level API (UploadDataType, DownloadDataType)
- Add support for .NET 3.5 and .NET Standard 1.4 (supports Universal Windows Platform 10.0)
- Add
FtpTrace.LogToConsole
andLogToFile
to control logging in .NET core version
- Add
PlainTextEncryption
API to support FTPS servers and plain-text FTP firewalls (CCC command) - FluentFTP now uses unsafe code to support the CCC command (inside
FtpSslStream
) - If you need a "non unsafe" version of the library please add an issue
- Add logging for high-level function calls to improve remote debugging (
FtpTrace.LogFunctions
) - Add settings to hide sensitive data from logs (
FtpTrace.LogIP
,LogUserName
,LogPassword
) - Add
RecursiveList
to control if recursive listing should be used - Auto-detect Windows CE and disable recursive listing during
DeleteDirectory()
- Add
UploadRateLimit
andDownloadRateLimit
to control the speed of data transfer (thanks Danie-Brink)
- Fix parsing of
LinkTarget
duringGetListing()
on Unix FTP servers - Improve logging clarity by removing "FluentFTP" prefix in TraceSource
- Add
MoveFile()
andMoveDirectory()
to move files and directories safely
- Automatically verify checksum of a file after upload/download (thanks jblacker)
- Configurable error handling (abort/throw/ignore) for file transfers (thanks jblacker)
- Multiple log levels for tracing/logging debug output in
FtpTrace
(thanks jblacker)
- Simplify
DeleteDirectory()
API - theforce
andfastMode
args are no longer required DeleteDirectory()
is faster since it uses one recursive file listing instead of many- Remove .NET Standard 1.4 to improve nuget update reliability, since we need 1.6 anyway
- Split stream API into
Upload()
/UploadFile()
andDownload()
/DownloadFile()
- Greatly improve performance of
FileExists()
andGetNameListing()
- Add new OS-specific directory listing parsers to
GetListing()
andGetObjectInfo()
- Support
GetObjectInfo()
even if machine listings are not supported by the server - Add
existsMode
toUploadFile()
andUploadFiles()
allowing for skip/overwrite and append - Remove all usages of string.Format to fix reliability issues caused with UTF filenames
- Fix issue of broken files when uploading/downloading through a proxy (thanks Zoltan666)
GetReply()
is now public so users ofOpenRead
/OpenAppend
/OpenWrite
can call it after
- Add async/await support to all methods for .NET 4.5 and onwards (thanks jblacker)
- Support for .NET Standard 1.4 added.
- Add
UploadFiles()
andDownloadFiles()
which is faster than single file transfers - Allow disabling UTF mode using DisableUTF8 API
- First .NET Core release (DNXCore5.0) using Visual Studio 2017 project and shared codebase.
- Support for .NET 2.0 also added with shims for LINQ commands needed.
- Add
FtpListOption.IncludeSelfAndParent
toGetListing
- Use streams during upload/download of files to improve performance with large files
- Support for uploading/downloading to Streams and byte[] with
UploadFile()
andDownloadFile()
- Added high-level
UploadFile()
andDownloadFile()
API. Fixed some race conditions.
- Added support for FTP proxies using HTTP 1.1 and User@Host modes. (thanks L3Z4)