FTP Tutorial
Back to tutorial list...
Table of content
# Namespaces and assemblies
To use the features of Rebex for .NET described here, you have to reference
the Rebex.Net.Ftp.dll assembly in your project.
It contains the Ftp and other classes in Rebex.Net namespace.
In your source files, import the following namespece:
C#
using Rebex.Net;
VB.NET
Imports Rebex.Net
back to top...
# FTP basics - connecting, logging in and disconnecting
Typical FTP session goes like this:
- Connect to the FTP server
- Login - authenticate with user name and password
- Browse directories and transfer files
- Disconnect
There are many FTP servers that allow anonymous access. You have to call the Login
method as well for these: just use "anonymous" for username and your e-mail address for password,
or try the "guest" password if you don't want to disclose your e-mail - most FTP servers allow this
as well. Or pass null (Nothing in Visual Basic) for username and password
to achieve the same thing.
And now let's look at some sample code.
C#
using Rebex.Net;
// ...
// create client and connect
Ftp client = new Ftp();
client.Connect("ftp.example.org");
// authenticate
client.Login("username", "password");
// browse directories, transfer files
// ...
// disconnect
client.Disconnect();
VB.NET
Imports Rebex.Net
' ...
' create client and connect
Dim client As New Ftp
client.Connect("ftp.example.org")
' authenticate
client.Login("username", "password")
' browse directories, transfer files
' ...
' disconnect
client.Disconnect()
During a single FTP session, only one operation such as file transfer can be active at the same time.
However, if you really need to transfer more files simultaneously, or browse directories while a file
transfer is in progress, you might initiate multiple FTP sessions to the same servers - most servers
are configured to allow this.
back to top...
# Working with directories
Working with directories (folders) on the FTP server is simple. The remote filesystem is organized
in the same way as in Un*x. If you are used to Windows, watch out for the two differencies -
a slash (/) is used instead of a backslash, and there is only a single root at "/",
no drive letters. A typical path to a file might look like "/pub/incoming/test.zip", for example.
C#
// create client, connect and log in
Ftp client = new Ftp();
client.Connect("ftp.example.org");
client.Login("username", "password");
// determine current directory
Console.WriteLine("Current directory: {0}", client.GetCurrentDirectory());
// create the 'top' directory at the root level
client.CreateDirectory("/top");
// create the 'first' directory in the '/top' directory
client.CreateDirectory("/top/first");
// change the current directory to '/top'
client.ChangeDirectory("/top");
// create the 'second' directory in the current folder
// (note: we used a relative path this time)
client.CreateDirectory("second");
// remove the 'first' directory we created earlier
client.RemoveDirectory("first");
// change the current directory to a parent,
// (note: '..' has the same meaning as in Windows and Un*x
client.ChangeDirectory("..");
VB.NET
' create client, connect and log in
Dim client As New Ftp
client.Connect("ftp.example.org")
client.Login("username", "password")
' determine current directory
Console.WriteLine("Current directory: {0}", client.GetCurrentDirectory())
' create the 'top' directory at the root level
client.CreateDirectory("/top")
' create the 'first' directory in the '/top' directory
client.CreateDirectory("/top/first")
' change the current directory to '/top'
client.ChangeDirectory("/top")
' create the 'second' directory in the current folder
' (note: we used a relative path this time)
client.CreateDirectory("second")
' remove the 'first' directory we created earlier
client.RemoveDirectory("first")
' change the current directory to a parent,
' (note: '..' has the same meaning as in Windows and Un*x
client.ChangeDirectory("..")
back to top...
# Uploading and downloading files
File transfers are the essential part of the FTP protocol and can be achieved using
the GetFile and PutFile methods. They accept the path to the local
file and the path to the remote file (both paths must include the filename) and return the
number of bytes transferred (as long integer).
Other variants are also available that accept local and remote offsets, or streams instead
of local files - it is easy to use .NET's MemoryStream to upload and download data
from and to memory instead of disk.
C#
// create client, connect and log in
Ftp client = new Ftp();
client.Connect("ftp.example.org");
client.Login("username", "password");
// upload the 'test.zip' file to the current directory at the server
client.PutFile(@"c:\data\test.zip", "test.zip");
// upload the 'index.html' file to the specified directory at the server
client.PutFile(@"c:\data\index.html", "/wwwroot/index.html");
// download the 'test.zip' file from the current directory at the server
client.GetFile("test.zip", @"c:\data\test.zip");
// download the 'index.html' file from the specified directory at the server
client.GetFile("/wwwroot/index.html", @"c:\data\index.html");
// upload a text using a MemoryStream
string message = "Hello from Rebex FTP for .NET!";
byte[] data = System.Text.Encoding.Default.GetBytes(message);
System.IO.MemoryStream ms = new System.IO.MemoryStream(data);
client.PutFile(ms, "message.txt");
VB.NET
' create client, connect and log in
Dim client As New Ftp
client.Connect("ftp.example.org")
client.Login("username", "password")
' upload the 'test.zip' file to the current directory at the server
client.PutFile("c:\data\test.zip", "test.zip")
' upload the 'index.html' file to the specified directory at the server
client.PutFile("c:\data\index.html", "/wwwroot/index.html")
' download the 'test.zip' file from the current directory at the server
client.GetFile("test.zip", "c:\data\test.zip")
' download the 'index.html' file from the specified directory at the server
client.GetFile("/wwwroot/index.html", "c:\data\index.html")
' upload a text using a MemoryStream
Dim message As String = "Hello from Rebex FTP for .NET!"
Dim data As Byte() = System.Text.Encoding.Default.GetBytes(message)
Dim ms As New System.IO.MemoryStream(data)
client.PutFile(ms, "message.txt")
back to top...
# List of files and directories
The format of the list of the contents of a directory is not defined by the FTP RFC,
and varies substantially from server to server. But with Rebex FTP, retrieving
and accessing the list of files in a directory is extremely easy - the GetList method
does all the hard work and parses all common list formats automatically!
The following code snippet displays the list of files in the remote directory to a console:
C#
// create client, connect and log in
Ftp client = new Ftp();
client.Connect("ftp.example.org");
client.Login("username", "password");
// select the desired directory
client.ChangeDirectory("path");
// retrieve and display the list of files and directories
FtpList list = client.GetList();
foreach (FtpItem item in list)
{
Console.Write(item.Modified.ToString("u"));
Console.Write(item.Size.ToString().PadLeft(10, ' '));
Console.Write(" {0}", item.Name);
Console.WriteLine();
}
VB.NET
' create client, connect and log in
Dim client As New Ftp
client.Connect("ftp.example.org")
client.Login("username", "password")
' select the desired directory
client.ChangeDirectory("path")
' retrieve and display the list of files and directories
Dim list As FtpList = client.GetList()
Dim item As FtpItem
For Each item In list
Console.Write(item.Modified.ToString("u"))
Console.Write(item.Size.ToString().PadLeft(10, ""c))
Console.Write(" {0}", item.Name)
Console.WriteLine()
Next item
back to top...
# Transferring multiple files and directories
Upload or download of multiple files is a very common task.
There are GetFiles and PutFiles methods that can be used to
transfer multiple files easily - just provide the source path (which can be a directory or
contain wildcards), destination path and transfer options.
C#
// create client, connect and log in
Ftp client = new Ftp();
client.Connect("ftp.example.org");
client.Login("username", "password");
// upload the content of 'c:\data' directory and all subdirectories
// to the '/wwwroot' directory at the server
client.PutFiles(@"c:\data\*", "/wwwroot", FtpBatchTransferOptions.Recursive);
// upload all '.html' files in 'c:\data' directory
// to the '/wwwroot' directory at the server
client.PutFiles(@"c:\data\*.html", "/wwwroot", FtpBatchTransferOptions.Default,
FtpActionOnExistingFiles.OverwriteAll);
// download the content of '/wwwroot' directory and all subdirectories
// at the server to the 'c:\data' directory
client.GetFiles("/wwwroot/*", @"c:\data", FtpBatchTransferOptions.Recursive);
// download all '.html' files in 'c:\data' directory at the server
// to the '/wwwroot' directory at the server
client.GetFiles("/wwwroot/*.html", @"c:\data", FtpBatchTransferOptions.Default,
FtpActionOnExistingFiles.OverwriteAll);
VB.NET
' create client, connect and log in
Dim client As New Ftp
client.Connect("ftp.example.org")
client.Login("username", "password")
' upload the content of 'c:\data' directory and all subdirectories
' to the '/wwwroot' directory at the server
client.PutFiles("c:\data\*", "/wwwroot", FtpBatchTransferOptions.Recursive)
' upload all '.html' files in 'c:\data' directory
' to the '/wwwroot' directory at the server
client.PutFiles("c:\data\*.html", "/wwwroot", FtpBatchTransferOptions.Default, _
FtpActionOnExistingFiles.OverwriteAll)
' download the content of '/wwwroot' directory and all subdirectories
' at the server to the 'c:\data' directory
client.GetFiles("/wwwroot/*", "c:\data", FtpBatchTransferOptions.Recursive)
' download all '.html' files in 'c:\data' directory at the server
' to the '/wwwroot' directory at the server
client.GetFiles("/wwwroot*.html", "c:\data", FtpBatchTransferOptions.Default, _
FtpActionOnExistingFiles.OverwriteAll)
For transferring files from the current directory use asterisk (*). For example client.GetFiles("*", localPath).
When transferring lots of files, things can occasionally go wrong due to unforeseen problems -
to be informed about such errors, use BatchTransferProblemDetected event that also makes
it possible to select the desired next action. To stay informed about what is currently going on,
use the BatchTransferProgress event.
C#
// add event handler that gets called when a problem is detected during the batch
// transfer (this is optional) - the event handler can select the desired next
// action
client.BatchTransferProblemDetected +=
new FtpBatchTransferProblemDetectedEventHandler(client_BatchTransferProblemDetected);
// add event handler that gets called when a significant action occurs during
// the batch transfer (this is optional)
client.BatchTransferProgress +=
new FtpBatchTransferProgressEventHandler(client_BatchTransferProgress);
// upload or download files
client.PutFiles(localPath, remotePath, FtpBatchTransferOptions.Recursive);
// of course, the client_BatchTransferProblemDetected and client_BatchTransferProgress methods
// have to be implemented - check out the BatchTransfer sample for more information
VB.NET
' add event handler that gets called when a problem is detected during the batch
' transfer (this is optional) - the event handler can select the desired next
' action
AddHandler client.BatchTransferProblemDetected, AddressOf client_BatchTransferProblemDetected
' add event handler that gets called when a significant action occurs during
' the batch transfer (this is optional)
AddHandler client.BatchTransferProgress, AddressOf client_BatchTransferProgress
' upload or download files
client.PutFiles(localPath, remotePath, FtpBatchTransferOptions.Recursive)
' of course, the client_BatchTransferProblemDetected and client_BatchTransferProgress methods
' have to be implemented - check out the BatchTransfer sample for more information
For more information about these events, check out the BatchTransfer
sample application!
back to top...
# Transfer compression - MODE Z
The basic FTP protocol transfers your data as-is without any kind of compression. For highly-compressible
data such as text files or database scripts, this is highly inefficient. To solve this, many FTP servers
introduced MODE Z, an alternative to MODE S and MODE B. In MODE Z, all
transfers are compressed using the ZLIB compression method, making transfers of highly compressible files
(such as TXT, BMP or DOC) much faster - this includes FTP directory listings retrieved using GetList,
GetRawList or GetNameList methods. On the other hand, MODE Z doesn't provide
any substantial speedup for files that are already compresses (such as ZIP, JPEG, PNG or DOCX files).
To enable MODE Z in Rebex FTP, just set the TransferMode property to FtpTransferMode.Zlib.
All data transfers will now use MODE Z if the FTP server supports it and fall back to MODE S if it doesn't.
C#
// create client, connect and log in
Ftp client = new Ftp();
client.Connect("ftp.example.org");
client.Login("username", "password");
// change the preferred transfer mode to MODE Z
client.TransferMode = FtpTransferMode.Zlib;
// upload the 'hugelist.txt' file to the specified directory at the server
client.PutFile(@"c:\data\hugelist.txt", "/wwwroot/hugelist.txt");
// download the 'hugelist.txt' file from the specified directory at the server
client.GetFile("/wwwroot/hugelist.txt", @"c:\data\hugelist.txt");
// change the preferred transfer mode to stream mode (default)
client.TransferMode = FtpTransferMode.Stream;
// upload the 'archive.zip' file to the specified directory at the server
client.PutFile(@"c:\data\archive.zip", "/wwwroot/archive.zip");
// download the 'archive.zip' file from the specified directory at the server
client.GetFile("/wwwroot/archive.zip", @"c:\data\archive.zip");
VB.NET
' create client, connect and log in
Dim client As New Ftp
client.Connect("ftp.example.org")
client.Login("username", "password")
' change the preferred transfer mode to MODE Z
client.TransferMode = FtpTransferMode.Zlib
' upload the 'hugelist.txt' file to the specified directory at the server
client.PutFile("c:\data\hugelist.txt", "/wwwroot/hugelist.txt")
' download the 'hugelist.txt' file from the specified directory at the server
client.GetFile("/wwwroot/hugelist.txt", "c:\data\hugelist.txt")
' change the preferred transfer mode to stream mode (default)
client.TransferMode = FtpTransferMode.Stream
' upload the 'archive.zip' file to the specified directory at the server
client.PutFile("c:\data\archive.zip", "/wwwroot/archive.zip")
' download the 'archive.zip' file from the specified directory at the server
client.GetFile("/wwwroot/archive.zip", "c:\data\archive.zip")
back to top...
# FtpWebRequest - Pluggable Protocol
There is also an alternative way to using the Ftp class to upload and download
files using the FTP protocol - the .NET Framework introduced Uri, WebRequest and WebResponse
classes for accessing internet resources through a request/response model and includes
support for HTTP protocol and file:// scheme to request local files.
Rebex FTP for .NET fits nicely into this model with its FtpWebRequest class, which provides
an FTP-specific implementation of WebRequest class. Once registered, WebRequest.Create can be
used for accessing files on FTP servers in addition to natively supported HTTP and HTTPS.
C#
// register the component for the FTP prefix
WebRequest.RegisterPrefix("ftp://", Rebex.Net.FtpWebRequest.Creator);
// WebRequest now supports ftp protocol in addition to HTTP/HTTPS
// and local files - the rest of this code snippet is protocol-agnostic
// create web request for the given URI
WebRequest request = WebRequest.Create("ftp://ftp.example.org/files/package.zip");
// get and read web response
WebResponse response = request.GetResponse();
Stream stream = response.GetResponseStream();
Stream local = File.Create("package.zip");
byte[] buffer = new byte[1024];
int n;
do
{
n = stream.Read(buffer, 0, buffer.Length);
local.Write(buffer, 0, n);
} while (n > 0);
// close both streams
stream.Close();
local.Close();
VB.NET
' register the component for the FTP prefix
WebRequest.RegisterPrefix("ftp://", Rebex.Net.FtpWebRequest.Creator)
' WebRequest now supports ftp protocol in addition to HTTP/HTTPS
' and local files - the rest of this code snippet is protocol-agnostic
' create web request for the given URI
Dim request As WebRequest = WebRequest.Create("ftp://ftp.example.org/files/package.zip")
' get and read web response
Dim response As WebResponse = request.GetResponse()
Dim stream As Stream = response.GetResponseStream()
Dim local As Stream = File.Create("package.zip")
Dim buffer(1023) As Byte
Dim n As Integer
Do
n = stream.Read(buffer, 0, buffer.Length)
local.Write(buffer, 0, n)
Loop While n > 0
' close both streams
stream.Close()
local.Close()
back to top...
# Working with proxies
The Ftp class supports connection through proxies of several types. Following proxy types are supported:
| Proxy type | Comment |
|---|
FtpProxyType.None | Direct connection. Default when no proxy is specified. |
FtpProxyType.Socks4 | Connection through Socks4 proxy. |
FtpProxyType.Socks4a | Connection through Socks4A proxy (capable of resolving domain names). |
FtpProxyType.Socks5 | Connection through Socks5 proxy. |
FtpProxyType.HttpConnect | Connection through HTTP proxy using CONNECT method. |
FtpProxyType.FtpOpen | Connection through FTP proxy using OPEN command. |
FtpProxyType.FtpSite | Connection through FTP proxy using SITE command. |
FtpProxyType.FtpUser | Connection through FTP proxy using USER command. |
C#
// initialize FTP client
Ftp client = new Ftp();
// setup proxy details
client.Proxy.ProxyType = FtpProxyType.Socks5;
client.Proxy.Host = proxyHostname;
client.Proxy.Port = proxyPort;
// add proxy username and password when needed
client.Proxy.UserName = proxyUsername;
client.Proxy.Password = proxyPassword;
// connect, login
client.Connect(hostname, port);
client.Login(username, password);
// do some work
// ...
// disconnect
client.Disconnect();
VB.NET
' initialize FTP client
Dim client As Ftp = New Ftp
' setup proxy details
client.Proxy.ProxyType = FtpProxyType.Socks5
client.Proxy.Host = proxyHostname
client.Proxy.Port = proxyPort
' add proxy username and password when needed
client.Proxy.UserName = proxyUsername
client.Proxy.Password = proxyPassword
' connect, login
client.Connect(hostname, port)
client.Login(username, password)
' do some work
' ...
' disconnect
client.Disconnect()
back to top...
# Using events and logging communication
In case something goes wrong, it is very useful to have a log of commands sent to
the server and responses received from it for diagnostics purposes. To make this
possible, the Ftp class declares the following events:
| Event name | Description |
|---|
| CommandSent | Occurs when a command (e.g. LIST or RETR) is sent to the server. |
| ResponseRead | Occurs when response is received from the server. |
| StateChanged |
Occurs when the session state changes, such as from Disconnected to Ready, from
Ready to Sending or from Sending to Reading. |
| TransferProgress | Occurs when a block of data is sent or received. |
The CommandSent or ResponseRead events are particularly useful for the purpose of
generating a communication log and the TransferProgress event can be used by a GUI
application to display amount of transfered data or a progress bar.
C#
Ftp client = new Ftp();
client.CommandSent += new FtpCommandSentEventHandler(client_CommandSent);
client.ResponseRead += new FtpResponseReadEventHandler(client_ResponseRead);
client.Connect("ftp.example.org");
// ...
private void client_CommandSent(object sender, FtpCommandSentEventArgs e)
{
Console.WriteLine("Command: {0}", e.Command);
}
private void client_ResponseRead(object sender, FtpResponseReadEventArgs e)
{
Console.WriteLine("Response: {0}", e.Response);
}
VB.NET
Dim client As New Ftp
AddHandler client.CommandSent, AddressOf client_CommandSent
AddHandler client.ResponseRead, AddressOf client_ResponseRead
client.Connect("ftp.example.org")
' ...
Public Sub client_CommandSent(ByVal sender As Object, ByVal e As _
FtpCommandSentEventArgs)
Console.WriteLine("Command: {0}", e.Command)
End Sub
Public Sub client_ResponseRead(ByVal sender As Object, ByVal e As _
FtpResponseReadEventArgs)
Console.WriteLine("Response: {0}", e.Response)
End Sub
back to top...
# Resuming file transfer
When file upload or download fails for some reason, it might be possible to resume the transfer
instead of jast starting all over again. With the help of .NET's stream classes and Rebex FTP's
PutFile and GetFile methods, resuming the transfer where it ended is easy.
Resuming download:
C#
// create client, connect and log in
Ftp client = new Ftp();
client.Connect("ftp.example.org");
client.Login("username", "password");
// get the length of the remote file.
// (we need to know where to resume the transfer)
long remoteOffset = client.GetFileLength(remotePath);
// open the local file for writing
Stream local = File.OpenWrite(localPath);
// resume the transfer if there is more data available
if (local.Length < remoteOffset)
{
// seek to the end and read the position
local.Seek(0, SeekOrigin.End);
remoteOffset = local.Position;
// transfer data
client.GetFile(remotePath, local, remoteOffset);
}
// close the local file
local.Close();
VB.NET
'create client, connect and log in
Dim client As New Ftp
client.Connect("ftp.example.org")
client.Login("username", "password")
' get the length of the remote file
' (we need to know where to resume the transfer)
Dim remoteOffset As Long
remoteOffset = client.GetFileLength(remotePath)
' open the local file for writing
Dim local As Stream = File.OpenWrite(localPath)
' resume the transfer if there is more data available
If local.Length < remoteOffset Then
' seek to the end and read the position
local.Seek(0, SeekOrigin.End)
remoteOffset = local.Position
' transfer data
client.GetFile(remotePath, local, remoteOffset)
End If
' close the local file
local.Close()
Resuming upload:
C#
// create client, connect and log in
Ftp client = new Ftp();
client.Connect("ftp.example.org");
client.Login("username", "password");
// get the length of the remote file
// (we need to know where to resume the transfer)
long remoteOffset = client.GetFileLength(remotePath);
// open the local file for reading
Stream local = File.OpenRead(localPath);
// resume the transfer if there is more data available
if (remoteOffset < local.Length)
{
// seek to the offset correspoding to the remote length
local.Seek(remoteOffset, SeekOrigin.Begin);
// transfer data
client.PutFile(local, remotePath, remoteOffset, -1);
}
// close the local file
local.Close();
VB.NET
'create client, connect and log in
Dim client As New Ftp
client.Connect("ftp.example.org")
client.Login("username", "password")
' get the length of the remote file
' (we need to know where to resume the transfer)
Dim remoteOffset As Long = client.GetFileLength(remotePath)
' open the local file for reading
Dim local As Stream = File.OpenRead(localPath)
' resume the transfer if there is more data available
If remoteOffset < local.Length Then
' seek to the offset correspoding to the remote length
local.Seek(remoteOffset, SeekOrigin.Begin)
' transfer data
client.PutFile(local, remotePath, remoteOffset, -1)
End If
' close the local file
local.Close()
Check out the ResumableTransfer sample application for a working implementation
of transfer resuming code!
back to top...
Back to tutorial list...