FluentFTP is a fully managed FTP and FTPS library for .NET & .NET Standard, optimized for speed. It provides extensive FTP commands, File uploads/downloads, SSL/TLS connections, Automatic directory listing parsing, File hashing/checksums, File permissions/CHMOD, FTP proxies, UTF-8 support, Async/await support, Powershell support and more.
It is written entirely in C#, with no external dependencies. FluentFTP is released under the permissive MIT License, so it can be used in both proprietary and free/open source applications.
If you need priority support for a specific issue, consider funding it using IssueHunt.
- Full support for FTP, FTPS (FTP over SSL), FTPS with client certificates and FTPS with CCC (for FTP firewalls)
- File management:
- File and directory listing for all major server types (Unix, Windows/IIS, Azure, Pure-FTPd, ProFTPD, Vax, VMS, OpenVMS, Tandem, HP NonStop Guardian, IBM OS/400, AS400, Windows CE, Serv-U, etc)
- Fully recursive directory listing and directory deletion (manual recursion and server-side recursion)
- Easily upload and download a file from the server with progress tracking
- Automatically verify the hash of a file & retry transfer if hash mismatches
- Configurable error handling (ignore/abort/throw) for multi-file transfers
- Easily read and write file data from the server using standard streams
- Create, append, read, write, rename, move and delete files and folders
- Recursively deletes folders and all its contents
- Get file/folder info (exists, size, security flags, modified date/time)
- Get and set file permissions (owner, group, other)
- Absolute or relative paths (relative to the "working directory")
- Get the hash/checksum of a file (SHA-1, SHA-256, SHA-512, and MD5)
- Dereference of symbolic links to calculate the linked file/folder
- Throttling of uploads and downloads with configurable speed limit
- FTP protocol:
- Automatic detection of working connection settings and automatic connection negotiation
- Automatic detection of the FTP server software and its capabilities
- Extensive support for FTP commands, including some server-specific commands
- Easily send server-specific FTP commands using the
Execute()
method - Explicit and Implicit SSL connections are supported for the control and data connections using .NET's
SslStream
- Passive and active data connections (PASV, EPSV, PORT and EPRT)
- Supports Unix CHMOD, PRET, ProFTPD's SITE MKDIR and RMDIR commands, Serv-U's RMDA command
- Supports FTP Proxies (User@Host, HTTP 1.1, BlueCoat)
- FTP command logging using
TraceListeners
(passwords omitted) to trace or log output to a file - SFTP is not supported as it is FTP over SSH, a completely different protocol (use SSH.NET for that)
- Asynchronous support:
- Synchronous and asynchronous methods using
async
/await
for all operations - Asynchronous methods for .NET 4.0 and below using
IAsyncResult
pattern (Begin*/End*) - All asynchronous methods can be cancelled midway by passing a
CancellationToken
- All asynchronous methods honor the
ReadTimeout
and automatically cancel themselves if timed out - Improves thread safety by cloning the FTP control connection for file transfers (optional)
- Implements its own internal locking in an effort to keep transactions synchronized
- Synchronous and asynchronous methods using
- Extensible:
- Easily add support for more proxy types (simply extend
FTPClientProxy
) - Easily add unsupported directory listing parsers (see the
CustomParser
example) - Easily add custom logging/tracing functionality using
FtpTrace.AddListener
- Easily add your own Powershell commands by extending the scripts in
FluentFTP.ps1
- Easily add support for more proxy types (simply extend
Stable binaries are released on NuGet, and contain everything you need to use FTP/FTPS in your .Net/CLR application. For usage see the Example Usage section and the Documentation section below.
- Nuget (latest)
- Release Notes (features and fixes per release)
FluentFTP works on .NET and .NET Standard/.NET Core.
Platform | Binaries Folder |
---|---|
.NET 2.0 | net20 |
.NET 3.5 | net35 |
.NET 4.0 | net40 |
.NET 4.5 | net45 |
.NET Standard 1.4 | netstandard1.4 |
.NET Standard 1.6 | netstandard1.6 |
.NET Standard 2.0 | netstandard2.0 |
FluentFTP is also supported on these platforms: (via .NET Standard)
- Mono 4.6
- Xamarin.iOS 10.0
- Xamarin.Android 10.0
- Universal Windows Platform 10.0
Binaries for all platforms are built from a single VS 2017 Project. You will need VS 2017 to build or contribute to FluentFTP.
// create an FTP client
FtpClient client = new FtpClient("123.123.123.123");
// if you don't specify login credentials, we use the "anonymous" user account
client.Credentials = new NetworkCredential("david", "pass123");
// begin connecting to the server
client.Connect();
// get a list of files and directories in the "/htdocs" folder
foreach (FtpListItem item in client.GetListing("/htdocs")) {
// if this is a file
if (item.Type == FtpFileSystemObjectType.File){
// get the file size
long size = client.GetFileSize(item.FullName);
}
// get modified date/time of the file or folder
DateTime time = client.GetModifiedTime(item.FullName);
// calculate a hash for the file on the server side (default algorithm)
FtpHash hash = client.GetHash(item.FullName);
}
// upload a file
client.UploadFile(@"C:\MyVideo.mp4", "/htdocs/MyVideo.mp4");
// rename the uploaded file
client.Rename("/htdocs/MyVideo.mp4", "/htdocs/MyVideo_2.mp4");
// download the file again
client.DownloadFile(@"C:\MyVideo_2.mp4", "/htdocs/MyVideo_2.mp4");
// delete the file
client.DeleteFile("/htdocs/MyVideo_2.mp4");
// delete a folder recursively
client.DeleteDirectory("/htdocs/extras/");
// check if a file exists
if (client.FileExists("/htdocs/big2.txt")){ }
// check if a folder exists
if (client.DirectoryExists("/htdocs/extras/")){ }
// upload a file and retry 3 times before giving up
client.RetryAttempts = 3;
client.UploadFile(@"C:\MyVideo.mp4", "/htdocs/big.txt", FtpExists.Overwrite, false, FtpVerify.Retry);
// disconnect! good bye!
client.Disconnect();
You can use FluentFTP to transfer files to your FTP servers from your Powershell scripts. To get started:
- Download all the files in the Powershell folder in this repo.
- Place the contents into
C:\Scripts
or any folder of your choice. - Run this in Powershell to make the FluentFTP functions usable:
>. C:\Scripts\FluentFTP.ps1 #Makes functions callable from PowerShell scripts
- Run the commands you need! (Example commands are given below)
> Show-FtpFile -Site ftp.mysite.com -User bob -Password secure -FtpDirectory pub -FtpFileName "text*"
> Rename-File -Site ftp.mysite.com -User bob -Password secure -FtpDirectory pub -oldName "Readme.txt -newName Readme.done"
> Send-FtpFile -Site ftp.mysite.com -User bob -Password secure -FtpDirectory pub -fileName "Read*"
> Get-FtpFile -Site ftp.mysite.com -User bob -Password secure -FtpDirectory pub -ftpfileName "Read*"
> Remove-FtpFile -Site ftp.mysite.com -User bob -Password secure -FtpDirectory pub -ftpfileName "Read*"
Help on each command can be printed by running these commands in Powershell:
> get-help -full Show-FtpFile
> get-help -full Rename-FtpFile
> get-help -full Send-FtpFile
> get-help -full Get-FtpFile
> get-help -full Remove-FtpFile
Note: Check these FAQs and commonly asked questions that have already been solved.
Logging FAQs
- How do I trace FTP commands for debugging?
- How do I log all FTP commands to a file for debugging?
- How do I log only critical errors to a file?
- How do I disable logging of function calls?
- How do I omit sensitive information from the logs?
- How do I use third-party logging frameworks like NLog?
Connection FAQs
- How do I auto-detect the correct connection settings?
- How do I auto-connect to an FTP or FTPS server?
- How do I connect with SSL/TLS? / How do I use FTPS?
- How do I validate the server's certificate when using FTPS?
- How do I connect to Azure using SSL/TLS?
- How do I connect with FTPS and then switch back down to plaintext FTP?
- How do I connect with SFTP?
- How do I login with an anonymous FTP account?
- How do I login with an FTP proxy?
- How do I detect the type of server I'm connecting to?
- How do I use client certificates to login with FTPS?
- How do I bundle an X509 certificate from a file?
File Transfer FAQs
- How can I track the progress of file transfers?
- How can I upload data created on the fly?
- How can I download data without saving it to disk?
- How can I resume downloading a file?
- How can I resume uploading a file?
- How can I throttle the speed of upload/download?
- How do I verify the hash/checksum of a file and retry if the checksum mismatches?
- How do I append to a file?
- How do I download files using the low-level API?
- How can I upload/download files with Unicode filenames when my server does not support UTF8?
File Management FAQs
- How does GetListing() work internally?
- How does GetListing() return a recursive file listing?
- What kind of hashing commands are supported?
Misc FAQs
- What does
EnableThreadSafeDataConnections
do? - How can I contribute some changes to FluentFTP?
- How do I submit a pull request?
Very Common Issues
- Unable to read data from the transport connection : An existing connection was forcibly closed by the remote host
- Timed out trying to read data from the socket stream!
- FTPS not working on Linux since SSL session resumption is not supported
Common Issues
- I'm getting login errors but I can login fine in Firefox/Filezilla
- FluentFTP fails to install in Visual Studio 2010 : 'System.Runtime' already has a dependency defined for 'FluentFTP'.
- After uploading a file with special characters like "Caffè.png" it appears as "Caff?.bmp" on the FTP server. The server supports only ASCII but "è" is ASCII. FileZilla can upload this file without problems.
- I cannot delete a file if the filename contains Russian letters. FileZilla can delete this file without problems.
- I keep getting TimeoutException's in my Azure WebApp
- Many commands don't work on Windows CE
- After successfully transfering a single file with OpenWrite/OpenAppend, the subsequent files fail with some random error, like "Malformed PASV response"
- SSL Negotiation is very slow during FTPS login
Complete API documentation for the FtpClient
class, which handles all FTP/FTPS functionality.
Note: All methods support synchronous and asynchronous versions. Simply add the "Async" postfix to a method for async
/await
syntax in .NET 4.5+, or add the "Begin"/"End" prefix to a method for .NET 4.0 and below.
-
new FtpClient() - Creates and returns a new FTP client instance.
-
Host - The FTP server IP or hostname. Required.
-
Port - The FTP port to connect to. Default: Auto (21 or 990 depending on FTPS config)
-
Credentials - The FTP username & password to use. Must be a valid user account registered with the server. Default:
anonymous/anonymous
-
Connect() - Connects to an FTP server (uses TLS/SSL if configured).
-
Disconnect() - Closes the connection to the server immediately.
-
AutoDetect() - Automatically discover working FTP connection settings and return those connection profiles.
-
AutoConnect() - Automatically discover working FTP connection settings and use those to connect to the server.
-
Execute() - Execute a custom or unsupported command.
-
IsConnected - Checks if the connection is still alive.
-
IsClone - Checks if this control connection is a clone. Default: false.
-
LastReply - Returns the last
FtpReply
received from the server.
-
ServerType - Gets the type of the FTP server software that we're connected to, using the
FtpServer
enum. See the list of supported FTP servers. Default:FtpServer.Unknown
-
ServerOS - Gets the operating system of the FTP server software that we're connected to, using the
FtpOS
enum. See the list of supported operating systems. Default:FtpOS.Unknown
-
SystemType - Gets the type of system/server that we're connected to.
-
Capabilities - Gets the server capabilities (represented by flags).
-
HasFeature() - Checks if a specific feature (
FtpCapability
) is supported by the server.
-
GetListing() - Get a file listing of the given directory. Add
FtpListOption.Recursive
to recursively list all the sub-directories as well. Returns oneFtpListItem
per file or folder with all available properties set. Each item contains:-
Type
: The type of the object. (File, Directory or Link) -
Name
: The name of the object. (minus the path) -
FullName
: The full file path of the object. If filenames look wrong, select the correct encoding. -
Created
: The created date/time of the object. Default:DateTime.MinValue
if not provided by server. -
Modified
: The last modified date/time of the object. If you get incorrect values, try adding theFtpListOption.Modify
flag which loads the modified date/time using anotherMDTM
command. Default:DateTime.MinValue
if not provided by server. -
Size
: The size of the file in bytes. If you get incorrect values, try adding theFtpListOption.Size
flag which loads the file size using anotherSIZE
command. Default:0
if not provided by server. -
LinkTarget
: The full file path the link points to. Only filled for symbolic links. -
LinkObject
: The file/folder the link points to. Only filled for symbolic links ifFtpListOption.DerefLink
flag is used. -
SpecialPermissions
: Gets special permissions such as Stiky, SUID and SGID. -
Chmod
: The CHMOD permissions of the object. For example 644 or 755. Default:0
if not provided by server. -
OwnerPermissions
: User rights. Any combination of 'r', 'w', 'x' (using theFtpPermission
enum). Default:FtpPermission.None
if not provided by server. -
GroupPermissions
: Group rights. Any combination of 'r', 'w', 'x' (using theFtpPermission
enum). Default:FtpPermission.None
if not provided by server. -
OtherPermissions
: Other rights. Any combination of 'r', 'w', 'x' (using theFtpPermission
enum). Default:FtpPermission.None
if not provided by server. -
RawPermissions
: The raw permissions string received for this object. Use this if other permission properties are blank or invalid. -
Input
: The raw string that the server returned for this object. Helps debug if the above properties have been correctly parsed.
-
-
GetNameListing() - A simple command that only returns the list of file paths in the given directory, using the NLST command.
-
GetObjectInfo() - Get information for a single file or directory as an
FtpListItem
. It includes the type, date created, date modified, file size, permissions/chmod and link target (if any).
-
Upload() - Uploads a Stream or byte[] to the server. Returns true if succeeded, false if failed or file does not exist. Exceptions are thrown for critical errors. Supports very large files since it uploads data in chunks.
-
Download() - Downloads a file from the server to a Stream or byte[]. Returns true if succeeded, false if failed or file does not exist. Exceptions are thrown for critical errors. Supports very large files since it downloads data in chunks.
-
UploadFile() - Uploads a file from the local file system to the server. Use
FtpExists.Append
to resume a partial upload. Returns true if succeeded, false if failed or file does not exist. Exceptions are thrown for critical errors. Supports very large files since it uploads data in chunks. Optionally verifies the hash of a file & retries transfer if hash mismatches. -
DownloadFile() - Downloads a file from the server to the local file system. Use
FtpLocalExists.Append
to resume a partial download. Returns true if succeeded, false if failed or file does not exist. Exceptions are thrown for critical errors. Supports very large files since it downloads data in chunks. Local directories are created if they do not exist. Optionally verifies the hash of a file & retries transfer if hash mismatches. -
UploadFiles() - Uploads multiple files from the local file system to a single folder on the server. Returns the number of files uploaded. Skipped files are not counted. User-defined error handling for exceptions during file upload (ignore/abort/throw). Optionally verifies the hash of a file & retries transfer if hash mismatches. Faster than calling
UploadFile()
multiple times. -
DownloadFiles() - Downloads multiple files from server to a single directory on the local file system. Returns the number of files downloaded. Skipped files are not counted. User-defined error handling for exceptions during file download (ignore/abort/throw). Optionally verifies the hash of a file & retries transfer if hash mismatches.
-
OpenRead() - (Prefer using
Download()
for downloading to aStream
orbyte[]
) Open a stream to the specified file for reading. Returns a standardStream
. Please callGetReply()
after you have successfully transfered the file to read the "OK" command sent by the server and prevent stale data on the socket. -
OpenWrite() - (Prefer using
Upload()
for uploading aStream
orbyte[]
) Opens a stream to the specified file for writing. Returns a standardStream
, any data written will overwrite the file, or create the file if it does not exist. Please callGetReply()
after you have successfully transfered the file to read the "OK" command sent by the server and prevent stale data on the socket. -
OpenAppend() - (Prefer using
Upload()
withFtpExists.Append
for uploading aStream
orbyte[]
) Opens a stream to the specified file for appending. Returns a standardStream
, any data written wil be appended to the end of the file. Please callGetReply()
after you have successfully transfered the file to read the "OK" command sent by the server and prevent stale data on the socket.
Working directory (relative paths are relative to this directory):
-
GetWorkingDirectory() - Gets the full path of the current working directory.
-
SetWorkingDirectory() - Sets the full path of the current working directory. All relative paths are relative to the working directory.
Directories:
-
DirectoryExists() - Check if a directory exists on the server.
-
CreateDirectory() - Creates a directory on the server. If the parent directories do not exist they are also created.
-
DeleteDirectory() - Deletes the specified directory on the server. If it is not empty then all subdirectories and files are recursively deleted.
-
MoveDirectory() - Moves a directory from one place to another on the server. The destination directory is deleted before moving if
FtpExists.Overwrite
is used. Only throws exceptions for critical errors.
Files:
-
FileExists() - Check if a file exists on the server.
-
DeleteFile() - Deletes the specified file on the server.
-
MoveFile() - Moves a file from one directory to another on the server. The destination file is deleted before moving if
FtpExists.Overwrite
is used. Only throws exceptions for critical errors. -
Rename() - Renames the file/directory on the server. Low level method that should NOT be used in most cases. Prefer
MoveFile()
andMoveDirectory()
. Throws exceptions if the source does not exist, or if the destination already exists. -
GetModifiedTime() - Gets the last modified date/time of the file or folder. Result may be in server timezone, local timezone or UTC, depending on
type
argument. -
SetModifiedTime() - Modifies the last modified date/time of the file or folder. Input may be in server timezone, local timezone or UTC, depending on
type
argument. -
GetFileSize() - Gets the size of the file in bytes, or -1 if not found.
-
DereferenceLink() - Recursively dereferences a symbolic link and returns the full path if found. The
MaximumDereferenceCount
property controls how deep we recurse before giving up.
Standard commands supported by most servers
-
GetChmod() - Gets the CHMOD permissions of the file/folder, or 0 if not found.
-
GetFilePermissions() - Gets the permissions of the given file/folder as an FtpListItem object with all "Permission" properties set, or null if not found.
Only supported by UNIX FTP servers which have the CHMOD extension installed and enabled.
-
Chmod() - Modifies the permissions of the given file/folder, given the CHMOD value.
-
SetFilePermissions() - Modifies the permissions of the given file/folder, given seperate owner/group/other values (
FtpPermission
enum).
(Note: The high-level file transfer API supports automatic hashing after upload/download).
Standard commands supported by most servers
-
HashAlgorithms - Get the hash types supported by the server, if any (represented by flags).
-
GetHash() - Gets the hash of an object on the server using the currently selected hash algorithm. Supported algorithms are available in the
HashAlgorithms
property. You should confirm that it's not equal toFtpHashAlgorithm.NONE
(which means the server does not support the HASH command). -
GetHashAlgorithm() - Query the server for the currently selected hash algorithm for the HASH command.
-
SetHashAlgorithm() - Selects a hash algorithm for the HASH command, and stores this selection on the server.
Non-standard commands supported by certain servers only. Learn more
-
GetChecksum() - Retrieves a checksum of the given file using a checksumming method that the server supports, if any. The algorithm used goes in this order : HASH, MD5, XMD5, XSHA1, XSHA256, XSHA512, XCRC.
-
GetMD5() - Retrieves the MD5 checksum of the given file, if the server supports it.
-
GetXMD5() - Retrieves the MD5 checksum of the given file, if the server supports it.
-
GetXSHA1() - Retrieves the SHA1 checksum of the given file, if the server supports it.
-
GetXSHA256() - Retrieves the SHA256 checksum of the given file, if the server supports it.
-
GetXSHA512() - Retrieves the SHA512 checksum of the given file, if the server supports it.
-
GetXCRC() - Retrieves the CRC32 checksum of the given file, if the server supports it.
Please import FluentFTP
to use these extension methods, or access them directly under the FtpExtensions
class.
-
GetFtpPath(path) - Converts the specified local file/directory path into a valid FTP file system path
-
GetFtpPath(path, segments) - Creates a valid FTP path by appending the specified segments to this string
-
GetFtpDirectoryName(path) - Gets the parent directory path of the given file path
-
GetFtpFileName(path) - Gets the file name and extension (if any) from the path
-
GetFtpDate(date, styles) - Tries to convert the string FTP date representation into a date time object
-
FileSizeToString(bytes) - Converts a file size in bytes to a string representation (eg.
12345
becomes12.3 KB
)
Please access these static methods directly under the FtpClient
class.
- GetPublicIP() - Use the Ipify service to calculate your public IP. Useful if you are behind a router or don't have a static IP.
Please see these FAQ entries for help on logging & debugging.
-
client.OnLogEvent - A property of
FtpClient
. Assign this to a callback that will be fired every time a message is logged. -
FtpTrace.LogFunctions - Include high-level function calls in logs? Default: true.
-
FtpTrace.LogIP - Include server IP addresses in logs? Default: true.
-
FtpTrace.LogUserName - Include FTP usernames in logs? Default: true.
-
FtpTrace.LogPassword - Include FTP passwords in logs? Default: false.
-
FtpTrace.LogPrefix - Log all messages prefixed with "FluentFTP". Default: false.
-
FtpTrace.WriteLine - Log a message or error to all registered listeners.
.NET Standard only
-
FtpTrace.LogToConsole - Should FTP communication be be logged to the console? Default: false.
-
FtpTrace.LogToFile - Set this to a file path to append all FTP communication to it. Default: false.
.NET Framework only
-
FtpTrace.FlushOnWrite - Flush trace listeners after writing each command. Default: true.
-
FtpTrace.AddListener - Add a logger to the system. Learn more
-
FtpTrace.RemoveListener - Remove a logger from the system.
You can automatically detect FTP connection settings that work with your server.
-
DataConnectionType - Active or Passive connection. Default: FtpDataConnectionType.AutoPassive (tries EPSV then PASV then gives up)
-
Encoding - Text encoding (ASCII or UTF8) used when talking with the server. ASCII is default, but upon connection, we switch to UTF8 if supported by the server. Manually setting this value overrides automatic detection. Default: Auto.
-
InternetProtocolVersions - Whether to use IPV4 and/or IPV6 when making a connection. All addresses returned during name resolution are tried until a successful connection is made. Default: Any.
-
UngracefullDisconnection - Disconnect from the server without sending QUIT. Default: false.
-
ActivePorts - List of ports to try using for Active FTP connections, or null to automatically select a port. Default: null.
-
AddressResolver - Delegate used for resolving local address, used for active data connections. This can be used in case you're behind a router, but port forwarding is configured to forward the ports from your router to your internal IP. In that case, we need to send the router's IP instead of our internal IP.
Set these before you call Connect()
. You can automatically detect FTPS connection settings that work with your server.
-
EncryptionMode - Type of SSL to use, or none. Explicit is TLS, Implicit is SSL. Default: FtpEncryptionMode.None.
-
DataConnectionEncryption - Indicates if data channel transfers should be encrypted. Default: true.
-
SslProtocols - Encryption protocols to use. Default: SslProtocols.Default.
-
SslBuffering - Whether to use SSL Buffering to speed up data transfer during FTP operations. Turn this off if you are having random issues with FTPS/SSL file transfer. Default: FtpsBuffering.Auto.
-
ClientCertificates - X509 client certificates to be used in SSL authentication process. Learn more.
-
ValidateCertificate - Event is fired to validate SSL certificates. If this event is not handled and there are errors validating the certificate the connection will be aborted.
-
ValidateAnyCertificate - Accept any SSL certificate received from the server and skip performing the validation using the
ValidateCertificate
callback. Useful for Powershell users. Default: false. -
ValidateCertificateRevocation - Indicates if the certificate revocation list is checked during authentication. Useful when you need to maintain the certificate chain validation, but skip the certificate revocation check. Default: true.
-
PlainTextEncryption - Disable encryption immediately after connecting with FTPS, using the CCC command. This is useful when you have a FTP firewall that requires plaintext FTP, but your server mandates FTPS connections. Default: false.
-
ListingParser - File listing parser to be used. Automatically calculated based on the type of the server, unless changed. File listing parsing has improved in 2017, but to use the older parsing routines please use
FtpParser.Legacy
. Default:FtpParser.Auto
. -
ListingCulture - Culture used to parse file listings. Default:
CultureInfo.InvariantCulture
. -
TimeConversion - Controls how timestamps returned by the server are converted. The default setting assumes that all servers return UTC. Default: DateTimeStyles.AssumeUniversal.
-
TimeOffset - Time difference between server and client, in hours. If the server is located in Amsterdam and you are in Los Angeles then the time difference is 9 hours. Default: 0.
-
RecursiveList - Uses predefined logic to check if your server supports a recursive LIST command. Set this to
true
if you are sure your server supports recursive listing. (LIST -R
). -
BulkListing - If true, increases performance of GetListing by reading multiple lines of the file listing at once. If false then GetListing will read file listings line-by-line. If GetListing is having issues with your server, set it to false. Default: true.
-
BulkListingLength - Bytes to read during GetListing. Only honored if BulkListing is true. Default: 128.
-
MaximumDereferenceCount - The maximum depth of recursion that
DereferenceLink()
will follow symbolic links before giving up. Default: 20.
-
RetryAttempts - The retry attempts allowed when a verification failure occurs during download or upload. Default: 1.
-
TransferChunkSize - Chunk size (in bytes) used during upload/download of files. Default: 65536 (65 KB).
-
UploadRateLimit - Rate limit for uploads (in kbyte/s), honored by high level API. Default: 0 (Unlimited).
-
DownloadRateLimit - Rate limit for downloads (in kbyte/s), honored by high level API. Default: 0 (Unlimited).
-
UploadDataType - Upload files in ASCII or Binary mode? Default: FtpDataType.Binary.
-
DownloadDataType - Download files in ASCII or Binary mode? Default: FtpDataType.Binary.
-
NoopInterval - Time to wait (in milliseconds) between sending NOOP commands to keep the control socket alive during long file transfers. Setting this interval too low will have a negative impact on performance. Setting this interval to 0 disables NOOP commands altogether. Decrease this setting if you are getting timeouts during file transfers. Read the PR notes for suggested values for this property. Default: 15000 (15 seconds).
-
ConnectTimeout - Time to wait (in milliseconds) for a connection attempt to succeed, before giving up. Default: 15000 (15 seconds).
-
ReadTimeout - Time to wait (in milliseconds) for data to be read from the underlying stream, before giving up. Honored by all asynchronous methods as well. Default: 15000 (15 seconds).
-
DataConnectionConnectTimeout - Time to wait (in milliseconds) for a data connection to be established, before giving up. Default: 15000 (15 seconds).
-
DataConnectionReadTimeout - Time to wait (in milliseconds) for the server to send data on the data channel, before giving up. Default: 15000 (15 seconds).
-
SocketPollInterval - Time that must pass (in milliseconds) since the last socket activity before calling
Poll()
on the socket to test for connectivity. Setting this interval too low will have a negative impact on performance. Setting this interval to 0 disables Polling altogether. Default: 15000 (15 seconds).
-
SocketKeepAlive - Set
SocketOption.KeepAlive
on all future stream sockets. Default: false. -
StaleDataCheck - Check if there is stale (unrequested data) sitting on the socket or not. In some cases the control connection may time out but before the server closes the connection it might send a 4xx response that was unexpected and can cause synchronization errors with transactions. To avoid this problem the Execute() method checks to see if there is any data available on the socket before executing a command. Default: true.
-
EnableThreadSafeDataConnections - Creates a new FTP connection for every file download and upload. This is slower but is a thread safe approach to make asynchronous operations on a single control connection transparent. Set this to
false
if your FTP server allows only one connection per username. Learn more Default: false.
Mapping table documenting supported FTP commands and the corresponding API..
Connection commands
Command | API | Description |
---|---|---|
USER, PASS | Credentials | Login with username & password |
QUIT | Disconnect() | Disconnect |
PASV, EPSV, EPRT | DataConnectionType | Passive & Active FTP modes |
FEAT | HasFeature() | Get the features supported by server |
SYST | GetSystem() | Get the server system type |
OPTS UTF8 ON | Encoding | Enables UTF-8 filenames |
OPTS UTF8 OFF | Encoding, DisableUTF8() | Disables UTF-8 filenames |
AUTH TLS | EncryptionMode | Switch to TLS/FTPS |
PBSZ, PROT | EncryptionMode and DataConnectionEncryption |
Configure TLS/FTPS connection |
CCC | PlainTextEncryption | Switch to plaintext FTP |
PRET | Automatic | Pre-transfer file information |
TYPE A | UploadDataType and DownloadDataType |
Transfer data in ASCII |
TYPE I | UploadDataType and DownloadDataType |
Transfer data in Binary |
File Management commands
Command | API | Description |
---|---|---|
MLSD | GetListing() | Get directory machine list |
LIST | GetListing() with FtpListOption.ForceList | Get directory file list |
NLST | GetNameListing() GetListing() with FtpListOption.ForceNameList |
Get directory name list |
LS | GetListing() with FtpListOption.UseLS | Get directory file list |
STAT | GetListing() with FtpListOption.UseStat | Get directory file list |
MLST | GetObjectInfo() | Get file information |
DELE | DeleteFile() | Delete a file |
MKD | CreateDirectory() | Create a directory |
SITE MKDIR | CreateDirectory() | Create a directory with server-side recursion (ProFTPD) |
RMD | DeleteDirectory() | Delete a directory |
SITE RMDIR | DeleteDirectory() | Delete a directory with server-side recursion (ProFTPD) |
RMDA | DeleteDirectory() | Delete a directory with server-side recursion (Serv-U) |
CWD | SetWorkingDirectory() | Change the working directory |
PWD | GetWorkingDirectory() | Get the working directory |
SIZE | GetFileSize() | Get the filesize in bytes |
MDTM | GetModifiedTime() GetListing() with FtpListOption.Modify GetObjectInfo() with dateModified |
Get the file modified date |
MFMT | SetModifiedTime() | Modify file modified date |
SITE CHMOD | Chmod() or SetFilePermissions() | Modify file permissions |
RNFR, RNTO | Rename() MoveFile() |
Rename a file or directory Move a file or directory |
NOOP | Upload() UploadFile() Download() DownloadFile() |
Keep-alive used during file transfer |
File Hashing commands
Command | API | Description |
---|---|---|
HASH | GetHash() | Gets the hash of a file |
OPTS HASH | GetHashAlgorithm() / SetHashAlgorithm() | Selects a hash algorithm for HASH command |
MD5 | GetChecksum() or GetMD5() | Gets the MD5 hash of a file |
XMD5 | GetChecksum() or GetXMD5() | Gets the MD5 hash of a file |
XSHA1 | GetChecksum() or GetXSHA1() | Gets the SHA-1 hash of a file |
XSHA256 | GetChecksum() or GetXSHA256() | Gets the SHA-256 hash of a file |
XSHA512 | GetChecksum() or GetXSHA512() | Gets the SHA-512 hash of a file |
How do I auto-detect the correct connection settings?
Use this code:
FtpClient client = new FtpClient(hostname, username, password); // or set Host & Credentials
var profiles = client.AutoDetect();
// if any profiles are found, print the code to the console
if (profiles.Count > 0){
var code = profiles[0].ToCode();
Console.WriteLine(code);
}
Once you find a working connection profile, use the generated code to quickly connect to your FTP server.
How do I auto-connect to an FTP or FTPS server?
Use this code:
FtpClient client = new FtpClient(hostname, username, password); // or set Host & Credentials
client.AutoConnect();
How do I connect with SSL/TLS? / How do I use FTPS?
Use this code:
FtpClient client = new FtpClient(hostname, username, password); // or set Host & Credentials
client.EncryptionMode = FtpEncryptionMode.Explicit;
client.SslProtocols = SslProtocols.Tls;
client.ValidateCertificate += new FtpSslValidation(OnValidateCertificate);
client.Connect();
void OnValidateCertificate(FtpClient control, FtpSslValidationEventArgs e) {
// add logic to test if certificate is valid here
e.Accept = true;
}
If you have issues connecting to the server, try using either of these:
Let the OS pick the highest and most relevant TLS protocol.
client.SslProtocols = Security.Authentication.SslProtocols.None;
Prevent the OS from using TLS 1.0 which has issues in .NET Framework.
client.SslProtocols = SslProtocols.Default | SslProtocols.Tls11 | SslProtocols.Tls12;
If you are on Linux and failing to connect via SSL/TLS, you may be having this issue.
How do I validate the server's certificate when using FTPS?
Method 1: Connect if the SSL certificate has no errors.
client.ValidateCertificate += new FtpSslValidation(delegate (FtpClient c, FtpSslValidationEventArgs e) {
if (e.PolicyErrors != System.Net.Security.SslPolicyErrors.None){
e.Accept = false;
}else{
e.Accept = true;
}
});
Method 2: Connect if the certificate matches a whitelisted certificate.
First you must discover the string of the valid certificate. Use this code to save the valid certificate string to a file:
client.ValidateCertificate += new FtpSslValidation(delegate (FtpClient c, FtpSslValidationEventArgs e) {
File.WriteAllText(@"C:\cert.txt", e.Certificate.GetRawCertDataString());
});
Then finally use this code to check if the received certificate matches the one you trust:
string ValidCert = "<insert contents of cert.txt>";
client.ValidateCertificate += new FtpSslValidation(delegate (FtpClient c, FtpSslValidationEventArgs e) {
if (e.PolicyErrors == SslPolicyErrors.None || e.Certificate.GetRawCertDataString() == ValidCert) {
e.Accept = true;
}else{
throw new Exception("Invalid certificate : " + e.PolicyErrors);
}
});
How do I connect to Azure using SSL/TLS?
Assuming you are using FTP publishing service on an Azure App Service instance.
If you have issues connecting to Azure, ensure you are not using "FTPS Only". As per the Azure documentation, "FTPS Only" does not support TLS 1.0 and 1.1 and this might break connectivity when trying to use FluentFTP with older versions of Windows. So when you try to connect to an Azure FTP instance that is blocking TLS 1.1 the connection silently fails because it only accepts TLS 1.2.
After changing the settings to allow insecure FTP, you can connect with FTPS using both Explicit and Implicit SSL modes.
How do I connect with FTPS and then switch back down to plaintext FTP?
This is useful when you have a FTP firewall that requires plaintext FTP, but your server mandates FTPS connections. We use the CCC command to instruct the server to revert back to FTP.
Set this option before calling Connect() or any other method on the FtpClient class.
client.PlainTextEncryption = true;
SFTP is not supported as it is FTP over SSH, a completely different protocol. Use SSH.NET for that.
How do I login with an anonymous FTP account? / I'm getting login errors but I can login fine in Firefox/Filezilla
Do NOT set the Credentials
property, so we can login anonymously. Or you can manually specify the following:
client.Credentials = new NetworkCredential("anonymous", "anonymous");
How do I login with an FTP proxy?
Create a new instance of FtpClientHttp11Proxy
or FtpClientUserAtHostProxy
and use FTP properties/methods like normal.
How can I track the progress of file transfers?
All of the high-level methods provide a progress
argument that can be used to track upload/download progress.
To use this, first create a callback method to provide to the Upload/Download method. This will be called with an FtpProgress
object, containing the percentage transferred as well as various statistics.
If you are creating your UI in WinForms, create a ProgressBar
with the Minimum
= 0 and Maximum
= 100.
Using the asynchronous API:
// Callback method that accepts a FtpProgress object
Progress<FtpProgress> progress = new Progress<FtpProgress>(x => {
// When progress in unknown, -1 will be sent
if (x.Progress < 0){
progressBar.IsIndeterminate = true;
}else{
progressBar.IsIndeterminate = false;
progressBar.Value = x;
}
});
Using the synchronous API:
// Callback method that accepts a FtpProgress object
Action<FtpProgress> progress = new Action<FtpProgress>(x => {
// When progress in unknown, -1 will be sent
if (x.Progress < 0){
progressBar.IsIndeterminate = true;
}else{
progressBar.IsIndeterminate = false;
progressBar.Value = x;
}
});
Now call the Upload/Download method providing the new progress
object that you just created.
Using the asynchronous API:
await client.DownloadFileAsync(localPath, remotePath, FtpLocalExists.Overwrite, FluentFTP.FtpVerify.Retry, progress);
Using the synchronous API:
client.DownloadFile(localPath, remotePath, FtpLocalExists.Overwrite, FluentFTP.FtpVerify.Retry, progress);
For .NET 2.0 users, pass an implementation of the IProgress
class. The Report()
method of the object you pass will be called with the progress value.
How can I upload data created on the fly?
Use Upload() for uploading a Stream
or byte[]
.
How can I download data without saving it to disk?
Use Download() for downloading to a Stream
or byte[]
.
How can I resume downloading a file?
Use DownloadFile() or DownloadFiles() with the existsMode
set to FtpLocalExists.Append
.
// download only the missing part of the file
// by comparing its file size to the size of the local file
client.DownloadFile(@"C:\MyVideo.mp4", "/htdocs/MyVideo.mp4", FtpLocalExists.Append);
Other options are:
-
FtpLocalExists.Skip
- If the local file exists, we blindly skip downloading it without any more checks. -
FtpLocalExists.Overwrite
- If the local file exists, we restart the download and overwrite the file. -
FtpLocalExists.Append
- If the local file exists, we resume the download by checking the local file size, and append the missing data to the file.
How can I resume uploading a file?
Using the new UploadFile() API:
// we compare the length of the offline file vs the online file,
// and only write the missing part to the server
client.UploadFile("C:\bigfile.iso", "/htdocs/bigfile.iso", FtpExists.Append);
How can I throttle the speed of upload/download?
Set the UploadRateLimit
and DownloadRateLimit
properties to control the speed of data transfer. Only honored by the high-level API, for both the synchronous and async versions, such as:
- Upload() / Download()
- UploadFile() / DownloadFile()
- UploadFiles() / DownloadFiles()
See this post for more information on the recent improvements to throttling.
How do I verify the hash/checksum of a file and retry if the checksum mismatches?
Add the FtpVerify
options to UploadFile() or DownloadFile() to enable automatic checksum verification.
// retry 3 times when uploading a file
client.RetryAttempts = 3;
// upload a file and retry 3 times before giving up
client.UploadFile(@"C:\MyVideo.mp4", "/htdocs/MyVideo.mp4", FtpExists.Overwrite, false, FtpVerify.Retry);
All the possible configurations are:
-
FtpVerify.OnlyChecksum
- Verify checksum, return true/false based on success. -
FtpVerify.Delete
- Verify checksum, delete target file if mismatch. -
FtpVerify.Retry
- Verify checksum, retry copying X times and then give up. -
FtpVerify.Retry | FtpVerify.Throw
- Verify checksum, retry copying X times, then throw an error if still mismatching. -
FtpVerify.Retry | FtpVerify.Delete
- Verify checksum, retry copying X times, then delete target file if still mismatching. -
FtpVerify.Retry | FtpVerify.Delete | FtpVerify.Throw
- Verify checksum, retry copying X times, delete target file if still mismatching, then throw an error
Using the UploadFile() API:
// append data to an existing copy of the file
File.AppendAllText(@"C:\readme.txt", "text to be appended" + Environment.NewLine);
// only the new part of readme.txt will be written to the server
client.UploadFile("C:\readme.txt", "/htdocs/readme.txt", FtpExists.Append);
Using the stream-based OpenAppend() API:
using (FtpClient conn = new FtpClient()) {
conn.Host = "localhost";
conn.Credentials = new NetworkCredential("ftptest", "ftptest");
using (Stream ostream = conn.OpenAppend("/full/or/relative/path/to/file")) {
try {
ostream.Position = ostream.Length;
var sr = new StreamWriter(ostream);
sr.WriteLine(...);
}
finally {
ostream.Close();
conn.GetReply(); // to read the success/failure response from the server
}
}
}
How do I download files using the low-level API?
Using the OpenRead() API:
// create remote FTP stream and local file stream
using (var remoteFileStream = client.OpenRead(remotePath, FtpDataType.Binary)){
using (var newFileStream = File.Create(localPath)){
// read 8KB at a time (you can increase this)
byte[] buffer = new byte[8 * 1024];
// download file to local stream
int len;
while ((len = remoteFileStream.Read(buffer, 0, buffer.Length)) > 0){
newFileStream.Write(buffer, 0, len);
}
}
}
// read the FTP response and prevent stale data on the socket
client.GetReply();
How can I upload/download files with Unicode filenames when my server does not support UTF8?
Set the connection encoding manually to ensure that special characters work properly.
The default codepage that you should use is 1252 Windows Western
. It has support for English + European characters (accented chars).
client.Encoding = System.Text.Encoding.GetEncoding(1252); // ANSI codepage 1252 (Windows Western)
Here is the full list of codepages based on the charset you need:
- 874 – English + Thai
- 1250 – English + Central Europe
- 1251 – English + Cyrillic (Russian)
- 1252 – English + European (accented characters)
- 1253 – English + Greek
- 1254 – English + Turkish
- 1255 – English + Hebrew
- 1256 – English + Arabic
- 1257 – English + Baltic
- 1258 – English + Vietnamese
How does GetListing() work internally?
-
When you call
GetListing()
, FluentFTP first attempts to use machine listings (MLSD command) if they are supported by the server. These are most accurate and you can expect correct file size and modification date (UTC). You may also force this mode usingclient.ListingParser = FtpParser.Machine
, and disable it with theFtpListOption.ForceList
flag. You should also include theFtpListOption.Modify
flag for the most accurate modification dates (down to the second). -
If machine listings are not supported we fallback to the appropriate OS-specific parser (LIST command), listed below. You may force usage of a specific parser using
client.ListingParser = FtpParser.*
.-
Unix parser : Works for Pure-FTPd, ProFTPD, vsftpd, etc. If you encounter errors you can always try the alternate Unix parser using
client.ListingParser = FtpParser.UnixAlt
. -
Windows parser : Works for IIS, DOS, Azure, FileZilla Server, etc.
-
VMS parser : Works for Vax, VMS, OpenVMS, etc.
-
NonStop parser : Works for Tandem, HP NonStop Guardian, etc.
-
IBM parser : Works for IBM OS/400, etc.
-
-
And if none of these satisfy you, you can fallback to name listings (NLST command), which are much slower than either LIST or MLSD. This is because NLST only sends a list of filenames, without any properties. The server has to be queried for the file size, modification date, and type (file/folder) on a file-by-file basis. Name listings can be forced using the
FtpListOption.ForceNameList
flag.
Note: Some FTP servers return no answer when listing an empty folder, so the client has no socket on the other side to communicate with. These exceptions are internally caught and an empty file listing is returned. If you need to check the implementation of this, search for all instances of FtpMissingSocketException
in the FluentFTP project.
How does GetListing() return a recursive file listing?
In older versions of FluentFTP, we assumed that all servers supported recursive listings via the LIST -R
command. However this caused numerous issues with various FTP servers that did not support recursive listings: The GetListing()
call would simply return the contents of the first directory without any of the child directories included.
Therefore, since version 20.0.0, we try to detect the FTP server software and if we determine that it does not support recursive listing, we do our own manual recursion. We begin by assuming that all servers do not support recursive listing, and then whitelist specific server types.
If you feel that GetListing()
is too slow when using recursive listings, and you know that your FTP server software supports the LIST -R
command, then please contribute support for your server:
-
Locate your FTP server type exists in the
FtpServer
enum. -
Update
FtpClient.RecursiveList()
to returntrue
for your server type.
What kind of hashing commands are supported?
We support XCRC, XMD5, and XSHA which are non-standard commands and contain no kind of formal specification. They are not guaranteed to work and you are strongly encouraged to check the FtpClient.Capabilities flags for the respective flag (XCRC, XMD5, XSHA1, XSHA256, XSHA512) before calling these methods.
Support for the MD5 command as described here has also been added. Again, check for FtpFeature.MD5 before executing the command.
Support for the HASH command has been added to FluentFTP. It supports retrieving SHA-1, SHA-256, SHA-512, and MD5 hashes from servers that support this feature. The returned object, FtpHash, has a method to check the result against a given stream or local file. You can read more about HASH in this draft.
How do I trace FTP commands for debugging?
Do this at program startup (since its static it takes effect for all FtpClient instances.)
.NET Framework version
FtpTrace.AddListener(new ConsoleTraceListener());
FtpTrace.LogUserName = false; // hide FTP user names
FtpTrace.LogPassword = false; // hide FTP passwords
FtpTrace.LogIP = false; // hide FTP server IP addresses
.NET Standard version
FtpTrace.LogToConsole = true;
FtpTrace.LogUserName = false; // hide FTP user names
FtpTrace.LogPassword = false; // hide FTP passwords
FtpTrace.LogIP = false; // hide FTP server IP addresses
Alternatively you can hook onto client.OnLogEvent
to get a callback every time a message is logged in the context of an individual FtpClient
instance.
How do I log all FTP commands to a file for debugging?
Do this at program startup (since its static it takes effect for all FtpClient instances.)
.NET Framework version
FtpTrace.AddListener(new TextWriterTraceListener("log_file.txt"));
FtpTrace.LogUserName = false; // hide FTP user names
FtpTrace.LogPassword = false; // hide FTP passwords
FtpTrace.LogIP = false; // hide FTP server IP addresses
.NET Standard version
FtpTrace.LogToFile = "log_file.txt";
FtpTrace.LogUserName = false; // hide FTP user names
FtpTrace.LogPassword = false; // hide FTP passwords
FtpTrace.LogIP = false; // hide FTP server IP addresses
How do I log only critical errors to a file?
This is the recommended configuration for a production server. Only supported in .NET Framework version.
Do this at program startup (since its static it takes effect for all FtpClient instances.)
FtpTrace.LogFunctions = false;
FtpTrace.AddListener(new TextWriterTraceListener("log_file.txt"){
Filter = new EventTypeFilter(SourceLevels.Error)
});
How do I disable logging of function calls?
Do this at program startup (since its static it takes effect for all FtpClient instances.)
FtpTrace.LogFunctions = false;
How do I omit sensitive information from the logs?
Use these settings to control what data is included in the logs:
FtpTrace.LogUserName
- Log FTP user names?FtpTrace.LogPassword
- Log FTP passwords?FtpTrace.LogIP
- Log FTP server IP addresses?
How do I use third-party logging frameworks like NLog?
FluentFTP has a built-in TraceSource
named "FluentFTP" that can be used for debugging and logging purposes. This is currently available for all .NET Framework versions except for .NET Standard. Any implementation of TraceListener
can be attached to the library either programmatically or via configuration in your app.config or web.config file. This will allow for direct logging or forwarding to third-party logging frameworks.
Most tracing messages are of type Verbose
or Information
and can typically be ignored unless debugging. Most ignored exceptions are classified as Warning
, but methods that return boolean for success/failure will log the failure reasons with the Error
level. If you are using .NET Standard and the DEBUG flag is set, then all logging messages will be issued via Debug.Write(message)
.
Attaching TraceListener in code:
TraceListener console = ConsoleTraceListener() {
Filter = new EventTypeFilter(SourceLevels.Verbose | SourceLevels.ActivityTracking)
};
FtpTrace.AddListener(console);
Attaching via configuration file:
<system.diagnostics>
<trace autoflush="true"></trace>
<sources>
<source name="FluentFTP">
<listeners>
<clear />
<!-- Attach a Console Listener -->
<add name="console />
<!-- Attach a File Trace Listener -->
<add name="file" />
<!-- Attach a Custom Listener -->
<add name="myLogger" />
<!--Attach NLog Trace Listener -->
<add name="nlog" />
</listeners>
</source>
</sources>
<sharedListeners>
<!--Define Console Listener -->
<add name="console" type="System.Diagnostics.ConsoleTraceListener" />
<!--Define File Listener -->
<add name="file" type="System.Diagnostics.TextWriterTraceListener
initializeData="outputFile.log">
<!--Only write errors -->
<filter type="System.Diagnostics.EventTypeFilter" initializeData="Error" />
</add>
<!--Define Custom Listener -->
<add name="custom" type="MyNamespace.MyCustomTraceListener />
<!-- Define NLog Logger -->
<add name="nlog" type="NLog.NLogTraceListener, NLog" />
</sharedListeners>
</system.diagnostics>
What does EnableThreadSafeDataConnections
do?
EnableThreadSafeDataConnections is an older feature built by the original author. If true, it opens a new FTP client instance (and reconnects to the server) every time you try to upload/download a file. It used to be the default setting, but it affects performance terribly so I disabled it and found many issues were solved as well as performance was restored. I believe if devs want multi-threaded uploading they should just start a new BackgroundWorker and create/use FtpClient within that thread. Try that if you want concurrent uploading, it should work fine.
How can I contribute some changes to FluentFTP? / How do I submit a pull request?
First you must "fork" FluentFTP, then make changes on your local version, then submit a "pull request" to request me to merge your changes. To do this:
- Click Fork on the top right of this page
- Open your version here : https://github.com/YOUR_GITHUB_USERNAME/FluentFTP
- Download Github Desktop and login to your account
- Click File > Clone repository... and select FluentFTP in the list
- Edit "Local path" with the folder where you want to place the source code and press Clone
- Edit the project using Visual Studio 2017 Community or better
- Switch to Github Desktop, which should now show a list of the changed files
- Type a Commit Summary (bottom left), and click Commit
- Click Push to origin (top right)
- Open the pull requests page to create a PR
- Click New pull request (top right)
- Click compare across forks (blue link, top right)
- On the right "head fork" select the fork with your username
- Click Create pull request
- Summarize the changes you made in the title
- Type details about the changes you made in the description
- Click Create pull request
- Thank you!
How do I detect the type of server I'm connecting to?
You can read ServerType
to get the exact type of FTP server software that you've connected to. We dynamically detect the FTP server software based on the welcome message it sends when you've just connected to it. We can currently detect:
- PureFTPd
- VsFTPd
- ProFTPD
- WuFTPd
- FileZilla Server
- OpenVMS
- Windows Server/IIS
- Windows CE
- GlobalScape EFT
- HP NonStop/Tandem
- Serv-U
- Cerberus
- CrushFTP
- glFTPd
- Homegate FTP
- BFTPd
- FTP2S3 Gateway
- XLight
- Solaris FTP
- IBM z/OS
You can also read ServerOS
to get the operating system of the FTP server you've connected to. We can detect:
- Windows
- Unix
- VMS
- IBM OS/400
- IBM z/OS
- SunOS
How do I use client certificates to login with FTPS?
Add your certificate into ClientCertificates
and then Connect()
.
client.EncryptionMode = FtpEncryptionMode.Explicit;
client.SslProtocols = SslProtocols.Tls | SslProtocols.Tls11 | SslProtocols.Tls12;
client.SocketKeepAlive = false;
client.ClientCertificates.Add(new X509Certificate2("C:\mycert.cer"));
client.ValidateCertificate += (control, e) => {
e.Accept = e.PolicyErrors == SslPolicyErrors.None;
};
client.Connect();
And ensure that:
-
You use
X509Certificate2
objects, not the incompleteX509Certificate
implementation. -
You do not use pem certificates, use p12 instead. See this Stack Overflow thread for more information. If you get SPPI exceptions with an inner exception about an unexpected or badly formatted message, you are probably using the wrong type of certificate.
How do I bundle an X509 certificate from a file?
You need the certificate added into your local store, and then do something like this:
FluentFTP.FtpClient client = new FluentFTP.FtpClient("WWW.MYSITE.COM", "USER","PASS");
// Select certificate and add to client
X509Store store = new X509Store("MY", StoreLocation.LocalMachine);
store.Open(OpenFlags.ReadOnly | OpenFlags.OpenExistingOnly);
X509Certificate2Collection collection = (X509Certificate2Collection)store.Certificates;
X509Certificate2Collection fcollection = (X509Certificate2Collection)collection.Find(X509FindType.FindByTimeValid, DateTime.Now, false);
X509Certificate2Collection scollection = X509Certificate2UI.SelectFromCollection(fcollection, "Select a certificate", "Select a certificate", X509SelectionFlag.MultiSelection);
if (scollection.Count != 1)
{
throw new Exception("Error: You have not chosen exactly one certificate");
}
foreach (X509Certificate2 x509 in scollection)
{
client.ClientCertificates.Add(x509);
}
store.Close();
//client.ReadTimeout = 10000;
client.Connect();
This is another way. And use X509Certificate2. I've been unable to get X509Certificate to work and from my reading it's because it's an incomplete implementation.
public void InitSFTP(){
FluentFTP.FtpClient client = new FluentFTP.FtpClient("WWW.MYSITE.COM", "USER", "PASS");
X509Certificate2 cert_grt = new X509Certificate2("C:\mycert.xyz");
client.EncryptionMode = FtpEncryptionMode.Explicit;
client.DataConnectionType = FtpDataConnectionType.PASV;
client.DataConnectionEncryption = true;
client.ClientCertificates.Add(cert_grt);
client.ValidateCertificate += new FtpSslValidation(OnValidateCertificate);
client.Connect();
}
private void OnValidateCertificate(FtpClient control, FtpSslValidationEventArgs e)
{
e.Accept = true;
}
FluentFTP fails to install in Visual Studio 2010 (VS2010) > 'System.Runtime' already has a dependency defined for 'FluentFTP'.
Your VS has an older version of nuget.exe
so it cannot properly install the latest FluentFTP. You must download nuget.exe` manually and run these commands:
cd D:\Projects\MyProjectDir
C:\Nuget\nuget.exe install FluentFTP
After uploading a file with special characters like "Caffè.png" it appears as "Caff?.bmp" on the FTP server. The server supports only ASCII but "è" is ASCII. FileZilla can upload this file without problems.
Set the connection encoding manually to ensure that special characters work properly.
The default codepage that you should use is 1252 Windows Western
. It has support for English + European characters (accented characters).
client.Encoding = System.Text.Encoding.GetEncoding(1252); // ANSI codepage 1252 (Windows Western)
I cannot delete a file if the filename contains Russian letters. FileZilla can delete this file without problems.
Set the connection encoding manually to ensure that special characters work properly.
For Russian you need to use the codepage 1251 Windows Cyrillic
client.Encoding = System.Text.Encoding.GetEncoding(1251); // ANSI codepage 1251 (Windows Cyrillic)
I keep getting TimeoutException's in my Azure WebApp
First try reducing the socket polling interval, which Azure needs.
client.SocketPollInterval = 1000;
If that doesn't work then try reducing the timeouts too.
client.SocketPollInterval = 1000;
client.ConnectTimeout = 2000;
client.ReadTimeout = 2000;
client.DataConnectionConnectTimeout = 2000;
client.DataConnectionReadTimeout = 2000;
If none of these work, remember that Azure has in intermittent bug wherein it changes the IP-address during a FTP request. The connection is established with IP-address A and for the data transfer Azure uses IP-address B and this isn't allowed on many firewalls. This is a known Azure bug.
Many commands don't work on Windows CE
According to this from MSDN the Windows CE implementation of FTP is the bare minimum, and open to customization via source code. Many advanced commands such as CHMOD are unsupported.
After successfully transfering a single file with OpenWrite/OpenAppend, the subsequent files fail with some random error, like "Malformed PASV response"
You need to call FtpReply status = GetReply()
after you finish transfering a file to ensure no stale data is left over, which can mess up subsequent commands.
SSL Negotiation is very slow during FTPS login
FluentFTP uses SslStream
under the hood which is part of the .NET framework. SslStream
uses a feature of windows for updating root CA's on the fly, which can cause a long delay in the certificate authentication process. This can cause issues in FluentFTP related to the SocketPollInterval
property used for checking for ungraceful disconnections between the client and server. This MSDN Blog covers the issue with SslStream
and talks about how to disable the auto-updating of the root CA's.
FluentFTP logs the time it takes to authenticate. If you think you are suffering from this problem then have a look at Examples\Debug.cs for information on retrieving debug information.
Unable to read data from the transport connection : An existing connection was forcibly closed by the remote host
This means that on the server the [FTP daemon] service isn't running (probably not the case) or the service is currently still busy performing another operation. It almost sounds like the server is returning a message indicating it is still performing the last operation.
Try reducing the polling interval to ensure that the connection does not time-out.
client.SocketPollInterval = 1000;