-
-
Couldn't load subscription status.
- Fork 679
File Transfer
Tip: For detailed documentation refer to the IntelliSense tips that appear when you call a given API method.
-
UploadStream() - Uploads a
Streamto the server. Returns true if succeeded, false if failed. Exceptions are thrown for critical errors. Supports very large files since it uploads data in chunks. Note: Your stream needs to provide its length at the start of the upload, as we cannot upload streams with unknown length. -
UploadBytes() - Uploads a
byte[]to the server. Returns true if succeeded, false if failed. Exceptions are thrown for critical errors. Supports very large files since it uploads data in chunks. -
DownloadStream() - Downloads a file from the server to a
Stream. Returns true if succeeded, false if failed or file does not exist. Exceptions are thrown for critical errors. Always throwsFtpMissingObjectExceptionif the requested file does not exist on the server. Supports very large files since it downloads data in chunks. -
DownloadBytes() - Downloads a file from the server to a
byte[]. Returns true if succeeded, false if failed or file does not exist. Exceptions are thrown for critical errors. Always throwsFtpMissingObjectExceptionif the requested file does not exist on the server. Supports very large files since it downloads data in chunks. -
DownloadUriBytes() - Connects to the FTP server specified by the FTP URI, downloads the file to a
byte[], and then disconnects. Exceptions are thrown for critical errors. Always throwsFtpMissingObjectExceptionif the requested file does not exist on the server. A one-liner replacement forHttpClient.GetByteArrayAsync(). Example URI:"ftps://myuser:[email protected]:21/var/log/test1.log" -
UploadFile() - Uploads a file from the local file system to the server. Use
FtpRemoteExists.Resumeto resume a partial upload andFtpRemoteExists.AddToEndto append the given data to the end. ReturnsFtpStatusto indicate success, skipped or failed. 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. Provides detailed progress tracking and metrics via callbacks by sending anFtpProgressobject. -
DownloadFile() - Downloads a file from the server to the local file system. Use
FtpLocalExists.Resumeto resume a partial download. ReturnsFtpStatusto indicate success, skipped or failed. Exceptions are thrown for critical errors. Always throwsFtpMissingObjectExceptionif the requested file does not exist on the server. 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. Provides detailed progress tracking and metrics via callbacks by sending anFtpProgressobject. -
UploadFiles() - Uploads multiple files from the local file system to a single folder on the server. Returns an
FtpResultobject with detailed information per file requested. 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 callingUploadFile()multiple times. Provides detailed progress tracking and metrics via callbacks by sending anFtpProgressobject. -
DownloadFiles() - Downloads multiple files from server to a single directory on the local file system. Returns an
FtpResultobject with detailed information per file requested. User-defined error handling for exceptions during file download (ignore/abort/throw). Optionally verifies the hash of a file & retries transfer if hash mismatches. Provides detailed progress tracking and metrics via callbacks by sending anFtpProgressobject.
-
Config.TransferChunkSize - Chunk size (in bytes) used during upload/download of files. Default: 65536 (65 KB).
-
Config.LocalFileBufferSize - Buffer size (in bytes) used for reading and writing files on the local file system. Default: 4096 (4 KB).
-
Config.LocalFileShareOption - File sharing mode used for reading files during file upload. Change it if you have file-locking issues. Default:
FileShare.Read
-
Config.UploadRateLimit - Rate limit for uploads (in kbyte/s), honored by high level API. Default: 0 (Unlimited).
-
Config.DownloadRateLimit - Rate limit for downloads (in kbyte/s), honored by high level API. Default: 0 (Unlimited).
-
Config.UploadDataType - Upload files in ASCII or Binary mode? Default:
FtpDataType.Binary. -
Config.DownloadDataType - Download files in ASCII or Binary mode? Default:
FtpDataType.Binary. -
Config.DownloadZeroByteFiles - If zero-byte files should be downloaded or not. Default: true.
-
Config.RetryAttempts - Retry attempts allowed when a verification failure occurs during download or upload. Default: 1.
-
Config.NoopInterval - See Noop.
-
High-level API
-
High-level API
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.
Use Upload() for uploading a Stream or byte[].
Use Download() for downloading to a Stream or byte[].
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.
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", FtpRemoteExists.Resume);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:
-
UploadBytes()/DownloadBytes() -
UploadFile()/DownloadFile() -
UploadFiles()/DownloadFiles()
See this post for more information on the recent improvements to throttling.
Using the UploadFile() API to upload only the newly added part of the file (eg. for log files):
// 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", FtpRemoteExists.Resume);Using the UploadFile() API to upload the given file to the end of the remote file:
// the entire readme.txt will be written to the end of the file on the serer
client.UploadFile("C:\readme.txt", "/htdocs/readme.txt", FtpRemoteExists.AddToEnd);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
}
}
}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
The return type between these 2 functions are fundamentally different for a very simple reason. They both behave differently.
-
DownloadFile
-
FtpStatusis sufficient as a return type because we only need to indicate the type of success/failure - Throws exceptions for errors (important also as these exceptions are caught by higher-order functions like
DownloadFiles) -
RemotePathandLocalPathare already provided to it by the caller, so it does not need to return it -
IsSkippedis already provided as a value in the enumFtpStatus -
IsSkippedByRuleis out of the question, as it has no rule mechanism for filtering files -
IsFailedis not required, just throws exceptions on failure -
TypeandIsDownloadare irrelevant, you know it is a file being downloaded
-
-
DownloadFiles
-
FtpStatusis NOT sufficient as a return type because we need to return multiple attributes per file, so we need to return a List ofFtpResultinstead. - Does NOT throws exceptions for errors because otherwise the entire function would abort. So instead just skip that one file if it fails.
-
RemotePathandLocalPathare NOT provided by the caller, but instead computed by the function, so it makes sense to return it back to the user -
IsSkippedis set when the file already exists so it does not need to re-transfer it -
IsSkippedByRuleis set when the file is filtered by rules -
IsFailedis required, because exceptions are not used to indicate a file was failed -
Typeis used to indicate if its a file/folder/link
-
Same reasoning applies to UploadFile and UploadFiles.
We like minimizing complexity, therefore using a simpler return type FtpStatus is better in this case because the more complex FtpResult is not required.
You can use the FtpResult.ToStatus() API to obtain a FtpStatus enum value and easily compare it against another enum value.
- Auto Connection
- Auto Reconnection
- FTP(S) Connection
- FTP(S) Connection using GnuTLS
- FTPS Proxies
- Custom Servers
- Custom Commands
- v40 Migration Guide