Ftp Features

Connection

Ultimate FTP makes it so easy to establish secure connections to your FTP servers.

Connect to an FTP server

In order to use the Ftp and other classes, you have to add references to ComponentPro.Ftp.dll, ComponentPro.Common.dll, ComponentPro.Network.dll, and ComponentPro.FileSystem.dll assemblies to your project.

To authenticate to an FTP server, you can simply perform the following steps

  • Add using directives to your code to create aliases for existing namespaces and avoid having to type the fully qualified type names.
  • Create a new instance of the Ftp class.
  • Now you can connect to the FTP server with Connect methods.
  • Call the Disconnect method to close the FTP session when done.
// Create a new class instance.
Ftp client = new Ftp();

// Connect to the FTP server.
client.Connect("myserver");

// Or you can specify the FTP port with
// client.Connect("myserver", 21);

// Authenticate.
client.Authenticate("userName", "password");

// Do something here...
client.DownloadFile("/my remote file.dat", "my local file");

// Disconnect.
client.Disconnect();
' Create a new class instance.
Dim client As New Ftp()

' Connect to the FTP server.
client.Connect("myserver")

' Or you can specify the FTP port with
' client.Connect("myserver", 21);

' Authenticate.
client.Authenticate("userName", "password")

' Do something here...
client.DownloadFile("/my remote file.dat", "my local file")

' Disconnect.
client.Disconnect()
// Create a new class instance.
using (Ftp client = new Ftp())
{
    // Connect to the FTP server.
    client.Connect("myserver", 21, SslSecurityMode.Explicit);

    // Authenticate.
    client.Authenticate("userName", "password");

    // Do something here...
    client.DownloadFile("/my remote file.dat", "my local file");
}
' Create a new class instance.
Using client As New Ftp()
    ' Connect to the FTP server.
    client.Connect("myserver", 21, SslSecurityMode.Explicit)

    ' Authenticate.
    client.Authenticate("userName", "password")

    ' Do something here...
    client.DownloadFile("/my remote file.dat", "my local file")
End Using

Explicit and Implicit SSL support

Explicit connection and Implicit connection are two secure methods used to connect to a secure FTP server. Ultimate FTP supports both Explicit and Implicit SSL modes.

It also allows you to upgrade an unsecured connection to secure or downgrade a secure connection to unsecure.

Data Transfer Encryption

To enable data transfer encryption, set the SecureDataTransfers property to true. To disable, set the that property to false.

Set connection settings

The Ftp class has several properties allowing you to set proxies, transfer mode and transfer type, Encoding, compression mode, EnabledFeatures, and more.

// Create a new instance of the Ftp class.
using (Ftp client = new Ftp())
{
    // Connect to the server.
    client.Connect(serverName);

    client.Authenticate(userName, password);

    client.Encoding = System.Text.Encoding.UTF8;
    client.TransferMode = FtpTransferMode.Zlib;

    // ...
    // Transfer files
    // ...
}
' Create a new instance of the Sftp class.
Using client As New Ftp()
    ' Connect to the server.
    client.Connect(serverName)

    client.Authenticate(userName, password)

    client.Encoding = System.Text.Encoding.UTF8
    client.TransferMode = FtpTransferMode.Zlib

    ' ...
    ' Transfer files
    ' ...
End Using
// Create a new instance of the Ftp class.
using (Ftp client = new Ftp())
{
    // Connect to the server.
    client.Connect(serverName);

    // Get connection information
    Console.WriteLine("Server: {0}:{1}, System Name: {2}",
                      client.ServerName, client.ServerPort, client.GetSystemName());

    // Authenticate the user
    client.Authenticate(userName, password);

    Console.WriteLine("Logged in as: {0}", client.UserName);
}
' Create a new instance of the Sftp class.
Using client As New Ftp()
    ' Connect to the server.
    client.Connect(serverName)

    ' Get connection information
    Console.WriteLine("Server: {0}:{1}, System Name: {2}", client.ServerName, client.ServerPort, client.GetSystemName())

    ' Authenticate the user
    client.Authenticate(userName, password)

    Console.WriteLine("Logged in as: {0}", client.UserName)
End Using

Get connection info

Some of the useful information about the current FTP session such as server/user name and system name are available when the connection is established or the user is authenticated.

Check connection state

To determine if a session is still alive, use GetConnectionState method. The method sends a "ping" command to the server to ensure the connection is still up and running.

// Check session state
using (Ftp client = new Ftp())
{
    // Connect to the server.
    client.Connect(serverName);

    // Authenticate the user
    client.Authenticate(userName, password);

    bool connected;
    int nativeErrorCode;
    // Get connection state.
    client.GetConnectionState(out connected, out nativeErrorCode);

    Console.WriteLine(connected ? "Connection is still alive" : "Connection closed. Error code: " + nativeErrorCode);
}
' Check session state
Using client As New Ftp()
    ' Connect to the server.
    client.Connect(serverName)

    ' Authenticate the user
    client.Authenticate(userName, password)

    Dim connected As Boolean
    Dim nativeErrorCode As Integer
    ' Get connection state.
    client.GetConnectionState(connected, nativeErrorCode)

    If connected Then
        Console.WriteLine("Connection is still alive")
    Else
        Console.WriteLine("Connection closed. Error code: " & nativeErrorCode)
    End If
End Using
static void Main()
{
    // Create a new class instance.
    Ftp client = new Ftp();

    client.CertificateReceived += client_CertificateReceived;

    // Connect to the FTP server.
    client.Connect("myserver", 21, SslSecurityMode.Explicit);

    // Authenticate.
    client.Authenticate("userName", "password");

    // Do something here...
    client.DownloadFile("/my remote file.dat", "my local file");

    // Disconnect.
    client.Disconnect();
}

/// <summary>
/// Returns all issues of the given certificate.
/// </summary>
/// <param name="status">The certificate verification result.</param>
/// <param name="code">The error code.</param>
/// <returns>Certificate problems.</returns>
private static string GetCertProblem(CertificateVerificationStatus status, int code)
{
    switch (status)
    {
        case CertificateVerificationStatus.TimeNotValid:
            return "Server's certificate has expired or is not valid yet.";

        case CertificateVerificationStatus.Revoked:
            return "Server's certificate has been revoked.";

        case CertificateVerificationStatus.UnknownCa:
            return "Server's certificate was issued by an unknown authority.";

        case CertificateVerificationStatus.UntrustedRoot:
            return "Server's certificate was issued by an untrusted authority.";

        case CertificateVerificationStatus.IncompleteChain:
            return "Server's certificate does not chain up to a trusted root authority.";

        case CertificateVerificationStatus.Malformed:
            return "Server's certificate is malformed.";

        case CertificateVerificationStatus.CnNotMatch:
            return "Server hostname does not match the certificate.";

        case CertificateVerificationStatus.UnknownError:
            return string.Format("Error {0:x} encountered while validating server's certificate.", code);

        default:
            return status.ToString();
    }
}

static void client_CertificateReceived(object sender, ComponentPro.Security.CertificateReceivedEventArgs e)
{
    X509Certificate2 cert = e.ServerCertificates[0];

    CertificateVerificationStatus status = e.Status;

    CertificateVerificationStatus[] values = (CertificateVerificationStatus[])Enum.GetValues(typeof(CertificateVerificationStatus));

    StringBuilder sbIssues = new StringBuilder();
    for (int i = 0; i < values.Length; i++)
    {
        // Matches the validation status?
        if ((status & values[i]) == 0)
            continue;

        // The issue is processed.
        status ^= values[i];

        sbIssues.AppendFormat("{0}\r\n", GetCertProblem(values[i], e.ErrorCode));
    }

    Console.WriteLine("Issue: " + sbIssues.ToString());

    Console.WriteLine("Subject: " + cert.SubjectName.Name);
    Console.WriteLine("Issuer: " + cert.IssuerName.Name);
    Console.WriteLine("Effective Date: " + cert.NotBefore);
    Console.WriteLine("Expiry Date: " + cert.NotAfter);
    Console.ResetColor();
    Console.Write("Do you want to accept this certificate (Add to trusted list, Yes, No) [a,y,n]?");

    string response = Console.ReadLine().Trim().ToLower();

    // Add certiticate of the issuer CA to the trusted list.
    if (response == "a")
    {
        e.AddToTrustedRoot = true;
    }
    else if (response == "y")
    {
        e.Accept = true;
    }
}
Shared Sub Main()
    ' Create a new class instance.
    Dim client As New Ftp()

    AddHandler client.CertificateReceived, AddressOf client_CertificateReceived

    ' Connect to the FTP server.
    client.Connect("myserver", 21, SslSecurityMode.Explicit)

    ' Authenticate.
    client.Authenticate("userName", "password")

    ' Do something here...
    client.DownloadFile("/my remote file.dat", "my local file")

    ' Disconnect.
    client.Disconnect()
End Sub

''' <summary>
''' Returns all issues of the given certificate.
''' </summary>
''' <param name="status">The certificate verification result.</param>
''' <param name="code">The error code.</param>
''' <returns>Certificate problems.</returns>
Private Shared Function GetCertProblem(ByVal status As CertificateVerificationStatus, ByVal code As Integer) As String
    Select Case status
        Case CertificateVerificationStatus.TimeNotValid
            Return "Server's certificate has expired or is not valid yet."

        Case CertificateVerificationStatus.Revoked
            Return "Server's certificate has been revoked."

        Case CertificateVerificationStatus.UnknownCa
            Return "Server's certificate was issued by an unknown authority."

        Case CertificateVerificationStatus.UntrustedRoot
            Return "Server's certificate was issued by an untrusted authority."

        Case CertificateVerificationStatus.IncompleteChain
            Return "Server's certificate does not chain up to a trusted root authority."

        Case CertificateVerificationStatus.Malformed
            Return "Server's certificate is malformed."

        Case CertificateVerificationStatus.CnNotMatch
            Return "Server hostname does not match the certificate."

        Case CertificateVerificationStatus.UnknownError
            Return String.Format("Error {0:x} encountered while validating server's certificate.", code)

        Case Else
            Return status.ToString()
    End Select
End Function

Private Shared Sub client_CertificateReceived(ByVal sender As Object, ByVal e As ComponentPro.Security.CertificateReceivedEventArgs)
    Dim cert As X509Certificate2 = e.ServerCertificates(0)

    Dim status As CertificateVerificationStatus = e.Status

    Dim values() As CertificateVerificationStatus = CType(System.Enum.GetValues(GetType(CertificateVerificationStatus)), CertificateVerificationStatus())

    Dim sbIssues As New StringBuilder()
    For i As Integer = 0 To values.Length - 1
        ' Matches the validation status?
        If (status And values(i)) = 0 Then
            Continue For
        End If

        ' The issue is processed.
        status = status Xor values(i)

        sbIssues.AppendFormat("{0}" & vbCrLf, GetCertProblem(values(i), e.ErrorCode))
    Next i

    Console.WriteLine("Issue: " & sbIssues.ToString())

    Console.WriteLine("Subject: " & cert.SubjectName.Name)
    Console.WriteLine("Issuer: " & cert.IssuerName.Name)
    Console.WriteLine("Effective Date: " & cert.NotBefore)
    Console.WriteLine("Expiry Date: " & cert.NotAfter)
    Console.ResetColor()
    Console.Write("Do you want to accept this certificate (Add to trusted list, Yes, No) [a,y,n]?")

    Dim response As String = Console.ReadLine().Trim().ToLower()

    ' Add certiticate of the issuer CA to the trusted list.
    If response = "a" Then
        e.AddToTrustedRoot = True
    ElseIf response = "y" Then
        e.Accept = True
    End If
End Sub

Verify server's certificate

By default Ftp validates certificate received from the server automatically. However, you can extend the process for a specific purpose like asking the user whether to accept or reject the server's certificate. You can easily customize the validation process by handling the CertificateReceived event of the Ftp class.

The example following will show you how to do that:

Automatic reconnect and resume transfer on failure

Auto reconnect

When the ReconnectionMaxRetries property is set to a value greater than 0, if an operation is interrupted due to a broken connection, the component automatically determines whether it should reconnect to the server.

Auto resume

If a file transfer is in progress, the component will automatically resume transfer when the connection is re-established.

// Create a new instance of the Ftp class.
using (Ftp client = new Ftp())
{
    // Connect to the server.
    client.Connect(serverName);

    // Authenticate the user
    client.Authenticate(userName, password);

    // Retry 2 times before reporting error.
    client.ReconnectionMaxRetries = 2;

    // If any error occurs while doing this operation, the client will check if reconnection is required.
    // It will retry 2 time before throwing error.
    FileInfoCollection list = client.ListDirectory("/data");

    // ...
}
' Create a new instance of the Ftp class.
Using client As New Ftp()
    ' Connect to the server.
    client.Connect(serverName)

    ' Authenticate the user
    client.Authenticate(userName, password)

    ' Retry 2 times before reporting error.
    client.ReconnectionMaxRetries = 2

    ' If any error occurs while doing this operation, the client will check if reconnection is required.
    ' It will retry 2 time before throwing error.
    Dim list As FileInfoCollection = client.ListDirectory("/data")

    ' ...
End Using
// Create a new instance of the Ftp class.
using (Ftp client = new Ftp())
{
    // Connect to the server.
    client.Connect(serverName);

    // Authenticate the user
    client.Authenticate(userName, password);

    // Retry 2 times before reporting error.
    client.ReconnectionMaxRetries = 2;

    // If any error occurs while doing this operation, the client will check if reconnection is required.
    // It will retry 2 time before throwing error.
    FileInfoCollection list = client.ListDirectory("/data");

    // ...
}
' Create a new instance of the Ftp class.
Using client As New Ftp()
    ' Connect to the server.
    client.Connect(serverName)

    ' Authenticate the user
    client.Authenticate(userName, password)

    ' Retry 2 times before reporting error.
    client.ReconnectionMaxRetries = 2

    ' If any error occurs while doing this operation, the client will check if reconnection is required.
    ' It will retry 2 time before throwing error.
    Dim list As FileInfoCollection = client.ListDirectory("/data")

    ' ...
End Using

Proxy servers

The Ultimate FTP component fully supports many proxy servers (often referred to as "proxies"). If you need to connect to your FTP server through a proxy, simply create a new instance of the FtpProxy class, set the appropriate properties of the FtpProxy object, and assign it to the Proxy property of the Ftp class, and the necessary proxy communication will take place.

Ultimate FTP component supports the following Proxy servers:

Proxy Name
SOCKS4 SOCKS4 proxy.
SOCKS4A SOCKS4A proxy (capable of resolving domain names).
SOCKS5 SOCKS5 proxy.
HTTP CONNECT HTTP proxy using CONNECT method.
Site Connection through FTP proxy using SITE command.
User Connection through FTP proxy using a single USER/PASS command.
Open Connection through FTP proxy using OPEN command.
DoubleLogin Connection through FTP proxy using two separate USER/PASS commands (one USER command for logging in the proxy and the second USER command for logging in the FTP server).

Authentication

Ultimate FTP supports many authentication methods including: password, password & account, and client certificates.

Authenticate with a password

To authenticate a user with password-based authentication, just use this Authenticate method overload. The first parameter is the name of the user, the second one is the user's password.

// Create a new class instance.
Ftp client = new Ftp();

// Connect to the FTP server.
client.Connect("myserver");

// Or you can specify the FTP port with
// client.Connect("myserver", 21);

// Authenticate.
client.Authenticate("userName", "password");

// Do something here...
client.DownloadFile("/my remote file.dat", "my local file");

// Disconnect.
client.Disconnect();
' Create a new class instance.
Dim client As New Ftp()

' Connect to the FTP server.
client.Connect("myserver")

' Or you can specify the FTP port with
' client.Connect("myserver", 21);

' Authenticate.
client.Authenticate("userName", "password")

' Do something here...
client.DownloadFile("/my remote file.dat", "my local file")

' Disconnect.
client.Disconnect()
// Create a new class instance.
using (Ftp client = new Ftp())
{
    // Connect to the FTP server.
    client.Connect("myserver", 21);

    // Authenticate.
    client.Authenticate("userName", "password", "account");

    // Do something here...
    client.DownloadFile("/my remote file.dat", "my local file");
}
' Create a new class instance.
Using client As New Ftp()
    ' Connect to the FTP server.
    client.Connect("myserver", 21)

    ' Authenticate.
    client.Authenticate("userName", "password", "account")

    ' Do something here...
    client.DownloadFile("/my remote file.dat", "my local file")
End Using

Authenticate with a password and account

Some FTP servers require an "account name" in addition to the username and password.

Authenticate with a client certificate

When connecting to a secure FTP/SSL server, it may ask the client for a certificate to authenticate the user. To provide a certificate for the authentication, handle the CertificateRequired event, and provide the certificate in the event handler. There are several ways doing that:

static void Main()
{
    // Create a new instance of the Ftp class.
    Ftp client = new Ftp();

    client.CertificateRequired += client_CertificateRequired;

    // Connect to the FTP server.
    client.Connect("myserver", 21, SslSecurityMode.Explicit);

    // Authenticate.
    client.Authenticate("userName", "password");

    // Do something here...
    client.DownloadFile("/my remote file.dat", "my local file");

    // Disconnect.
    client.Disconnect();
}

static void client_CertificateRequired(object sender, ComponentPro.Security.CertificateRequiredEventArgs e)
{
    // Load certificates from the local machine.
    X509Store my = new X509Store(StoreName.My, StoreLocation.CurrentUser);
    my.Open(OpenFlags.ReadOnly);

    // Retrieve a list of available certificates.
    X509Certificate2Collection certs = my.Certificates;

    // If no certificate found, return.
    if (certs.Count == 0)
    {
        e.Certificates = null;
        return;
    }

    // Show all certificates.
    Console.WriteLine("Select certificate:");
    for (int i = 0; i <= certs.Count; i++)
    {
        if (i == 0)
        {
            Console.WriteLine(string.Format("{0}. [Nothing, skip this step]", i));
            continue;
        }

        Console.WriteLine(string.Format("{0}. {1}", i, certs[i - 1].SubjectName.Name));
    }

    // And ask user to choose an appropriate certificate.
    while (true)
    {
        Console.Write(string.Format("Select certificate [0 - {0}]: ", certs.Count));

        int certIndex;

        try
        {
            certIndex = int.Parse(Console.ReadLine());
        }
        catch
        {
            Console.WriteLine("ERROR: Wrong certificate index input!");
            continue;
        }

        if (certIndex > 0 && certIndex <= certs.Count)
        {
            e.Certificates = new X509Certificate2Collection(certs[certIndex]);
            return;
        }

        if (certIndex == 0)
            break;

        Console.WriteLine(string.Format("ERROR: You must enter number between 0 and {0}.", certs.Count));
    }
}
Shared Sub Main()
    ' Create a new instance of the Ftp class.
    Dim client As New Ftp()

    AddHandler client.CertificateRequired, AddressOf client_CertificateRequired

    ' Connect to the FTP server.
    client.Connect("myserver", 21, SslSecurityMode.Explicit)

    ' Authenticate.
    client.Authenticate("userName", "password")

    ' Do something here...
    client.DownloadFile("/my remote file.dat", "my local file")

    ' Disconnect.
    client.Disconnect()
End Sub

Private Shared Sub client_CertificateRequired(ByVal sender As Object, ByVal e As ComponentPro.Security.CertificateRequiredEventArgs)
    ' Load certificates from the local machine.
    Dim my As New X509Store(StoreName.My, StoreLocation.CurrentUser)
    my.Open(OpenFlags.ReadOnly)

    ' Retrieve a list of available certificates.
    Dim certs As X509Certificate2Collection = my.Certificates

    ' If no certificate found, return.
    If certs.Count = 0 Then
        e.Certificates = Nothing
        Return
    End If

    ' Show all certificates.
    Console.WriteLine("Select certificate:")
    For i As Integer = 0 To certs.Count
        If i = 0 Then
            Console.WriteLine(String.Format("{0}. [Nothing, skip this step]", i))
            Continue For
        End If

        Console.WriteLine(String.Format("{0}. {1}", i, certs(i - 1).SubjectName.Name))
    Next i

    ' And ask user to choose an appropriate certificate.
    Do
        Console.Write(String.Format("Select certificate [0 - {0}]: ", certs.Count))

        Dim certIndex As Integer

        Try
            certIndex = Integer.Parse(Console.ReadLine())
        Catch
            Console.WriteLine("ERROR: Wrong certificate index input!")
            Continue Do
        End Try

        If certIndex > 0 AndAlso certIndex <= certs.Count Then
            e.Certificates = New X509Certificate2Collection(certs(certIndex))
            Return
        End If

        If certIndex = 0 Then
            Exit Do
        End If

        Console.WriteLine(String.Format("ERROR: You must enter number between 0 and {0}.", certs.Count))
    Loop
End Sub

Upload and download a single file

In addition to the capability of uploading and downloading a single file, you can also specify ZLIB compression mode, ASCII or Binary transfer mode, Active and Passive mode. The library comes with a built-in support for long path on Windows. It also allow you to resume interupted file transfer, upload/download file to/from another file system other than local disk file system.

Upload data from a file or stream

It is very easy to upload data from a local file or a stream. To upload data from a stream to the remote FTP server, simply use the UploadFile method which has two parameters, or another version of the UploadFile method for transferring data starting from a specific stream position. The first parameter is the data stream object and the second one is the remote file path. It returns the number of bytes transferred.

// Create a new class instance.
Ftp client = new Ftp();

// Connect to the FTP server.
client.Connect("localhost");

// Authenticate.
client.Authenticate("test", "test");

// ...

FileStream fi = new FileStream("c:\\test.dat", FileMode.Open);

// Upload data from a stream to '/test.dat'.
client.UploadFile(fi, "/test.dat");

fi.Close();

// ...

// Disconnect.
client.Disconnect();
' Create a new class instance.
Dim client As New Ftp()

' Connect to the FTP server.
client.Connect("localhost")

' Authenticate.
client.Authenticate("test", "test")

' ...

Dim fi As New FileStream("c:\test.dat", FileMode.Open)

' Upload data from a stream to '/test.dat'.
client.UploadFile(fi, "/test.dat")

fi.Close()

' ...

' Disconnect.
client.Disconnect()
// Create a new class instance.
Ftp client = new Ftp();

// Connect to the FTP server.
client.Connect("localhost");

// Authenticate.
client.Authenticate("test", "test");

// ...

// Create new file
FileStream fo = new FileStream("c:\\file.dat", FileMode.Create);

// Download remote file '/test.dat' to 'c:\test.dat'
client.DownloadFile("/test.dat", fo);

fo.Close();

// ...

// Disconnect.
client.Disconnect();
' Create a new class instance.
Dim client As New Ftp()

' Connect to the FTP server.
client.Connect("localhost")

' Authenticate.
client.Authenticate("test", "test")

' ...

' Create new file
Dim fo As New FileStream("c:\file.dat", FileMode.Create)

' Download remote file '/test.dat' to 'c:\test.dat'
client.DownloadFile("/test.dat", fo)

fo.Close()

' ...

' Disconnect.
client.Disconnect()

Download a remote file to a local file or stream

To download data from the remote file to a stream, simply use the DownloadFile method which has two parameters, or another version of the DownloadFile method for transferring data starting from a specific stream position. The first parameter is the remote file path and the second one is the data stream object. It returns the number of bytes transferred.

ZLIB transfer compression

You can enable the ZLIB compression mode to speed up data transfers and communication. For highly compressible files such as text files, the compression ratio can be up to 10:1, making the ZLIB compression mode very useful. However, the transfer speed might be slower when compressing already-compressed files.

The compression mode is enabled by setting the Config.EnableCompression to true before connecting to the server:

// Create a new instance of the Sftp class.
using (Ftp client = new Ftp())
{
    // Turn on transfer compression. By default, the TransferMode property is set to Stream.
    client.TransferMode = FtpTransferMode.Zlib;
    // If you wish to turn off transfer compression
    // client.TransferMode = FtpTransferMode.Stream;
    // Connect to the server
    client.Connect("server");
    // ...
}
' Create a new instance of the Sftp class.
Using client As New Ftp()
    ' Turn on transfer compression. By default, the TransferMode property is set to Stream.
    client.TransferMode = FtpTransferMode.Zlib
    ' If you wish to turn off transfer compression
    ' client.TransferMode = FtpTransferMode.Stream;
    ' Connect to the server
    client.Connect("server")
    ' ...
End Using
// Create a new Ftp instance.
Ftp client = new Ftp();

// Connect to the FTP server.
client.Connect("localhost");

// Authenticate.
client.Authenticate("test", "test");

// ...

// Resume uploading local file 'c:\test.dat' to '/test.dat'.
client.ResumeUploadFile("c:\\test.dat", "/test.dat");

// ...

// Disconnect.
client.Disconnect();
' Create a new Ftp instance.
Dim client As New Ftp()

' Connect to the FTP server.
client.Connect("localhost")

' Authenticate.
client.Authenticate("test", "test")

' ...

' Resume uploading local file 'c:\test.dat' to '/test.dat'.
client.ResumeUploadFile("c:\test.dat", "/test.dat")

' ...

' Disconnect.
client.Disconnect()

Resume single file transfers

To resume a file upload, use the ResumeUploadFile method. Similarly, to resume a file download, use the ResumeDownloadFile method. The following code snippet demonstrates how to continue a transfer that was interrupted or canceled.

ASCII and binary transfer modes

Ultimate SFTP supports two transfer mode: Binary (default) and ASCII. In binary mode (by setting the TransferType property to Binary), data is transferred as is without any processing. When text data is transferred between platforms that use different end-of-line sequences (Windows use <CR><LF> Unix uses <LF>), the transferred text data is unchanged and may be unfriendly presented to the user. It's essential to have the library convert the sequences automatically. To achieve that, set the TransferType property to Ascii.

// Set transfer type to ASCII
client.TransferType = FileTransferType.Ascii;
// Upload TXT files.
client.Upload(@"c:\data\*.txt", "/data");
' Set transfer type to ASCII
client.TransferType = FileTransferType.Ascii
' Upload TXT files.
client.Upload("c:\data\*.txt", "/data")
// Create a new class instance.
Ftp client = new Ftp();

// Connect to the FTP server.
client.Connect("localhost");

// Authenticate.
client.Authenticate("test", "test");

// ...

// Download remote file '/test.dat' to 'c:\test.dat'
client.DownloadFile("/test.dat", "c:\\test.dat", 1024, 1024, -1);

// ...

// Disconnect.
client.Disconnect();
' Create a new class instance.
Dim client As New Ftp()

' Connect to the FTP server.
client.Connect("localhost")

' Authenticate.
client.Authenticate("test", "test")

' ...

' Download remote file '/test.dat' to 'c:\test.dat'
client.DownloadFile("/test.dat", "c:\test.dat", 1024, 1024, -1)

' ...

' Disconnect.
client.Disconnect()

Read part of a remote file

To download part of a remote file, specify the remoteOffset and length parameters of this DownloadFile method overload.

Large file support

Ultimate SFTP supports two transfer modes: Binary and ASCII. The SFTP protocol's maximum supported file size is 2^63 bytes = 9,223,372 TB. However, some underlying filesystems do not support large file size. FAT16 and FAT32 are two examples; they support 2GB and 4GB maximum file size respectively. For other filesystems, see this table.

There is still a workaround for the filesystems that can't store files larger than 4GB. The stream-based file transfer API supports reading file from small pieces and combine them all together to have the large file.

// Create a new class instance.
Ftp client = new Ftp();

// Connect to the FTP server.
client.Connect("localhost");

// Authenticate.
client.Authenticate("test", "test");

// ...

// Upload local file 'c:\test.dat' to '/test.dat'.
client.UploadFile("c:\\test.dat", "/test.dat");

// ...

// Disconnect.
client.Disconnect();
' Create a new class instance.
Dim client As New Ftp()

' Connect to the FTP server.
client.Connect("localhost")

' Authenticate.
client.Authenticate("test", "test")

' ...

' Upload local file 'c:\test.dat' to '/test.dat'.
client.UploadFile("c:\test.dat", "/test.dat")

' ...

' Disconnect.
client.Disconnect()
// Create a new class instance.
using (Ftp client = new Ftp())
{            
    // Connect to the FTP server.
    client.Connect("localhost");

    // Authenticate.
    client.Authenticate("test", "test");

    string localPath = @"D:\Data\dailyReport.xml";
    string remotePath = "/Data/reports.xml";
    long localFileLength = new FileInfo(localPath).Length;
    long remoteFileLength = client.GetFileLength(remotePath);

    // Append header for 'dailyReport.xml' to 'reports.xml' on the server from memory
    string reportHeader = string.Format("<path>{0}</path>\n", localPath);
    MemoryStream ms = new MemoryStream(System.Text.Encoding.UTF8.GetBytes(reportHeader));
    client.UploadFile(ms, remotePath,
        remoteFileLength,   // Remote offset
        ms.Length);         // The number of bytes to upload

    // Update remote length
    remoteFileLength += ms.Length;

    // Append data from 'dailyReport.xml' to 'reports.xml' on the server
    client.UploadFile(localPath, remotePath,
        0,                 // Local offset
        remoteFileLength,  // Remote offset
        localFileLength);  // The number of bytes to upload

    // Disconnect.
    client.Disconnect();
}
' Create a new class instance.
Using client As New Ftp()
    ' Connect to the FTP server.
    client.Connect("localhost")

    ' Authenticate.
    client.Authenticate("test", "test")

    Dim localPath As String = "D:\Data\dailyReport.xml"
    Dim remotePath As String = "/Data/reports.xml"
    Dim localFileLength As Long = (New FileInfo(localPath)).Length
    Dim remoteFileLength As Long = client.GetFileLength(remotePath)

    ' Append header for 'dailyReport.xml' to 'reports.xml' on the server from memory
    Dim reportHeader As String = String.Format("<path>{0}</path>" & vbLf, localPath)
    Dim ms As New MemoryStream(System.Text.Encoding.UTF8.GetBytes(reportHeader))
    client.UploadFile(ms, remotePath, remoteFileLength, ms.Length) ' The number of bytes to upload -  Remote offset

    ' Update remote length
    remoteFileLength += ms.Length

    ' Append data from 'dailyReport.xml' to 'reports.xml' on the server
    client.UploadFile(localPath, remotePath, 0, remoteFileLength, localFileLength) ' The number of bytes to upload -  Remote offset -  Local offset

    ' Disconnect.
    client.Disconnect()
End Using

Append data to an existing file

The UploadFile and DownloadFile methods make it possible to upload or download a part of a file. This is often used for appending data to an existing file, or to resume broken transfers. Of course, it is possible to write/read data to/from any other position in a file as well.

To upload and download specific file part, use three additional parameters: local offset, remote offset, and the number of bytes you want to transfer. Local offset is not required for stream-based methods - data is read/written from/to the current stream position.

Download a remote file to another file system

To download a file from an SFTP server to another file system, use the CopyTo methods.

The following example demonstrates how to connect to FTP and SFTP servers, and use the CopyTo method to directly copy a file from the SFTP file system to the FTP file system.

// Connect to an FTP file system.
Ftp ftpsys = new Ftp();
ftpsys.Connect("192.168.126.128", 21);
ftpsys.Authenticate("test", "test");

// Connect to an SFTP file system.
Sftp sftp = new Sftp();
sftp.Connect("192.168.126.128", 2222);
sftp.Authenticate("test", "test");

// Copy 'my blog on SFTP file system.txt' file from the SFTP file system to the FTP file system.
sftp.CopyTo("my blog on SFTP file system.txt", ftpsys, "blog.txt");

ftpsys.Disconnect();
sftp.Disconnect();
' Connect to an FTP file system.
Dim ftpsys As New Ftp()
ftpsys.Connect("192.168.126.128", 21)
ftpsys.Authenticate("test", "test")

' Connect to an SFTP file system.
Dim sftp As New Sftp()
sftp.Connect("192.168.126.128", 2222)
sftp.Authenticate("test", "test")

' Copy 'my blog on SFTP file system.txt' file from the SFTP file system to the FTP file system.
sftp.CopyTo("my blog on SFTP file system.txt", ftpsys, "blog.txt")

ftpsys.Disconnect()
sftp.Disconnect()
// Connect to an FTP file system.
Ftp ftpsys = new Ftp();
ftpsys.Connect("192.168.126.128", 21);
ftpsys.Authenticate("test", "test");

// Connect to an SFTP file system.
Sftp sftp = new Sftp();
sftp.Connect("192.168.126.128", 2222);
sftp.Authenticate("test", "test");

// Copy 'blog.txt' file from the SFTP file system to the FTP file system.
sftp.CopyTo("blog.txt", ftpsys, "my blog on FTP file system.txt");

ftpsys.Disconnect();
sftp.Disconnect();
' Connect to an FTP file system.
Dim ftpsys As New Ftp()
ftpsys.Connect("192.168.126.128", 21)
ftpsys.Authenticate("test", "test")

' Connect to an SFTP file system.
Dim sftp As New Sftp()
sftp.Connect("192.168.126.128", 2222)
sftp.Authenticate("test", "test")

' Copy 'blog.txt' file from the SFTP file system to the FTP file system.
sftp.CopyTo("blog.txt", ftpsys, "my blog on FTP file system.txt")

ftpsys.Disconnect()
sftp.Disconnect()

Upload data from a file on another file system

To upload a file from another file system to an FTP server, simply use the CopyTo methods.

The following example demonstrates how to connect to FTP and SFTP servers, and use the CopyTo method to directly copy a file from the FTP file system to the SFTP file system.

Chunk file download

Ultimate FTP allows you to break a large file into multiple ones of a smaller set size so that the file can be downloaded faster. The following code snippet illustrates how to download many small pieces of a large file simultaneously.

static void Main()
{
    // Create a new class instance.
    using (Ftp client = new Ftp())
    {
        // Connect to the FTP server.
        client.Connect("myserver");

        // Authenticate.
        client.Authenticate("userName", "password");

        // ...

        client.Progress += ClientOnProgress;
        client.MultiPartDownload("/folder/remotefile.dat", "c:\\localfile.dat", 5, DownloadErrorHandler, DownloadCompletedHandler);

        // ...
    }
}

static void DownloadErrorHandler(MultiPartDownloadErrorEventArgs e)
{
    Console.WriteLine("Error: " + e.Error.Message);
    Console.Write("Do you want to retry (y/n)?");
    int c = Console.Read();
    if (c == 'y')
        e.Retry = true;
}

static void DownloadCompletedHandler(MultiPartDownloadResult result)
{
    Console.WriteLine("Success: " + result.Success);
}

private static void ClientOnProgress(object sender, FileSystemProgressEventArgs e)
{
    Console.WriteLine("Progression Percentage: " + e.Percentage);
}
Shared Sub Main()
    ' Create a new class instance.
    Using client As New Ftp()
        ' Connect to the FTP server.
        client.Connect("myserver")

        ' Authenticate.
        client.Authenticate("userName", "password")

        ' ...

        AddHandler client.Progress, AddressOf ClientOnProgress
        client.MultiPartDownload("/folder/remotefile.dat", "c:\localfile.dat", 5, AddressOf DownloadErrorHandler, AddressOf DownloadCompletedHandler)

        ' ...
    End Using
End Sub

Private Shared Sub DownloadErrorHandler(ByVal e As MultiPartDownloadErrorEventArgs)
    Console.WriteLine("Error: " & e.Error.Message)
    Console.Write("Do you want to retry (y/n)?")
    Dim c As Integer = Console.Read()
    If c = AscW("y"c) Then
        e.Retry = True
    End If
End Sub

Private Shared Sub DownloadCompletedHandler(ByVal result As MultiPartDownloadResult)
    Console.WriteLine("Success: " & result.Success)
End Sub

Private Shared Sub ClientOnProgress(ByVal sender As Object, ByVal e As FileSystemProgressEventArgs)
    Console.WriteLine("Progression Percentage: " & e.Percentage)
End Sub
// Create a new instance of the Ftp class.
using (Ftp client = new Ftp())
{
    // Connect to the server.
    client.Connect(serverName);

    client.Authenticate(userName, password);

    // Switch to Active mode
    client.Passive = false;

    // ...
    // Transfer files
    // ...
}
Region 'ActivePassive' not found in 'C:\Inetpub\vhosts\componentpro.com\httpdocs\Sites\ComponentPro\CodeExamples\Ftp\VB\Tutorial\IntuitiveApi.vb'. Example file is ignored.

Active and passive transfer modes

Ultimate FTP uses passive transfer mode by default to transfer data smoothly with most firewalls. You can change to Active transfer mode by setting the Passive property to false.

Long path support

All the file and directory management API permit an extended-length path for a maximum total path length of 32,767 characters.

// Create a new instance of the Ftp class.
using (Ftp client = new Ftp())
{
    // Connect to the server.
    client.Connect(serverName);

    // Authenticate the user
    client.Authenticate(userName, password);

    // Download a file to a directory with extra long path
    client.DownloadFile("/remote file.dat", @"c:\very long long long long long long long long long long long long long long long long long long long long long long long long long long long\very long long long long long long long long long long long long long long long long long long long long long long long long long long long long long long long long\file.dat");

    // Upload multiple files from a directory with extra long path
    client.Upload(@"c:\very long long long long long long long long long long long long long long long long long long long long long long long long long long long\very long long long long long long long long long long long long long long long long long long long long long long long long long long long long long long long long", "/data");

    // ...
}
' Create a new instance of the Ftp class.
Using client As New Ftp()
    ' Connect to the server.
    client.Connect(serverName)

    ' Authenticate the user
    client.Authenticate(userName, password)

    ' Download a file to a directory with extra long path
    client.DownloadFile("/remote file.dat", "c:\very long long long long long long long long long long long long long long long long long long long long long long long long long long long\very long long long long long long long long long long long long long long long long long long long long long long long long long long long long long long long long\file.dat")

    ' Upload multiple files from a directory with extra long path
    client.Upload("c:\very long long long long long long long long long long long long long long long long long long long long long long long long long long long\very long long long long long long long long long long long long long long long long long long long long long long long long long long long long long long long long", "/data")

    ' ...
End Using

Manage a single remote file

This section covers the single file features. You can easily check existence, delete, rename/move, calculate checksum, get file info, set permissions or create remote files with a single line of code.

Delete file

To delete a remote file, just call the DeleteFile method. The following code example shows how to delete a remote file on the FTP server:

// Create a new class instance.
Ftp client = new Ftp();

// Connect to the FTP server.
client.Connect("myserver");

// Authenticate.
client.Authenticate("userName", "password");

// ...

// Delete remote file '/test.dat'.
client.DeleteFile("/test.dat");

// ...

// Disconnect.
client.Disconnect();
' Create a new class instance.
Dim client As New Ftp()

' Connect to the FTP server.
client.Connect("myserver")

' Authenticate.
client.Authenticate("userName", "password")

' ...

' Delete remote file '/test.dat'.
client.DeleteFile("/test.dat")

' ...

' Disconnect.
client.Disconnect()
// Create a new class instance.
Ftp client = new Ftp();

// Connect to the FTP server.
client.Connect("myserver");

// Authenticate.
client.Authenticate("userName", "password");

// ...

// Determine whether file 'myFile.dat' exists or not.
if (client.FileExists("/myFile.dat"))
    Console.WriteLine("File '/myFile.dat' exists");
else
    Console.WriteLine("File '/myFile.dat' does not exist");

// ...

// Disconnect.
client.Disconnect();
' Create a new class instance.
Dim client As New Ftp()

' Connect to the FTP server.
client.Connect("myserver")

' Authenticate.
client.Authenticate("userName", "password")

' ...

' Determine whether file 'myFile.dat' exists or not.
If client.FileExists("/myFile.dat") Then
    Console.WriteLine("File '/myFile.dat' exists")
Else
    Console.WriteLine("File '/myFile.dat' does not exist")
End If

' ...

' Disconnect.
client.Disconnect()

Check file existence

To determine whether a remote file exists or not, you can use the FileExists method. You just need to pass the path of the remote file to check to the FileExists method, and it returns a boolean value indicating the specified file exists or not.

Rename/move a file

To rename a file, use the Rename method. It also supports moving a remote file to another location.

// Create a new class instance.
Ftp client = new Ftp();

// Connect to the FTP server.
client.Connect("myserver");

// Authenticate.
client.Authenticate("userName", "password");

// ...

// Rename remote file '/file.dat' to 'myfile.dat'
client.Rename("/file.dat", "/myfile.dat");

// Move a file
client.Rename("/file2.dat", "/new-folder/file2.dat");

// Rename a remote directory
client.Rename("/album-folder", "/old-album-folder");

// Move a directory
client.Rename("/album-folder2", "/new-folder/album-folder2");

// ...

// Disconnect.
client.Disconnect();
' Create a new class instance.
Dim client As New Ftp()

' Connect to the FTP server.
client.Connect("myserver")

' Authenticate.
client.Authenticate("userName", "password")

' ...

' Rename remote file '/file.dat' to 'myfile.dat'
client.Rename("/file.dat", "/myfile.dat")

' Move a file
client.Rename("/file2.dat", "/new-folder/file2.dat")

' Rename a remote directory
client.Rename("/album-folder", "/old-album-folder")

' Move a directory
client.Rename("/album-folder2", "/new-folder/album-folder2")

' ...

' Disconnect.
client.Disconnect()
// Create a new class instance.
using (Ftp client = new Ftp())
{
    // Connect to the FTP server.
    client.Connect("localhost");
    // Authenticate.
    client.Authenticate("test", "test");

    string checksum = client.GetFileChecksum(ComponentPro.IO.FileChecksumType.SHA1, "/data/test.dat");
}
' Create a new class instance.
Using client As New Ftp()
    ' Connect to the FTP server.
    client.Connect("localhost")
    ' Authenticate.
    client.Authenticate("test", "test")

    Dim checksum As String = client.GetFileChecksum(ComponentPro.IO.FileChecksumType.SHA1, "/data/test.dat")
End Using

Get file checksum

Some FTP servers support checksum calculation so the client can make use of the checksums to ensure that the files are uploaded/downloaded correctly by comparing the server checksum with of the local files.

Get file size

You can easily get the length of a remote file with the GetFileLength method of the Ftp class.

// Create a new class instance.
Ftp client = new Ftp();

// Connect to the FTP server.
client.Connect("localhost");

// Authenticate.
client.Authenticate("test", "test");

// ...

// Get size in bytes of the remote file '/test.dat'.
long length = client.GetFileLength("/test.dat");
Console.WriteLine("'/test.dat' file length is: {0} bytes", length);

// ...

// Disconnect.
client.Disconnect();
' Create a new class instance.
Dim client As New Ftp()

' Connect to the FTP server.
client.Connect("localhost")

' Authenticate.
client.Authenticate("test", "test")

' ...

' Get size in bytes of the remote file '/test.dat'.
Dim length As Long = client.GetFileLength("/test.dat")
Console.WriteLine("'/test.dat' file length is: {0} bytes", length)

' ...

' Disconnect.
client.Disconnect()
// Create a new class instance.
Ftp client = new Ftp();

// Connect to the FTP server.
client.Connect("localhost");

// Authenticate.
client.Authenticate("test", "test");

// ...

// Get information of remote file '/test.dat'.
FtpFileInfo info = (FtpFileInfo)client.GetItemInfo("/test.dat");
Console.WriteLine("Name: {0}, FullName: {1}, Permissions: {2}", info.Name, info.FullName, info.Permissions);

// ...

// Disconnect.
client.Disconnect();
' Create a new class instance.
Dim client As New Ftp()

' Connect to the FTP server.
client.Connect("localhost")

' Authenticate.
client.Authenticate("test", "test")

' ...

' Get information of remote file '/test.dat'.
Dim info As FtpFileInfo = CType(client.GetItemInfo("/test.dat"), FtpFileInfo)
Console.WriteLine("Name: {0}, FullName: {1}, Permissions: {2}", info.Name, info.FullName, info.Permissions)

' ...

' Disconnect.
client.Disconnect()

Get file info

To get information of a remote file, just use the GetItemInfo method of the Ftp class.

Get and set file last write time

To get last modification date and time of a remote file or directory, use the GetLastWriteTime method of the Ftp class. To set it, use the SetLastWriteTime method. The following example shows you how easy it is to do that:

// Create a new class instance.
Ftp client = new Ftp();

// Connect to the FTP server.
client.Connect("myserver");

// Authenticate.
client.Authenticate("test", "test");

// ...

// Get modified date and time of the remote file '/test.dat'.
DateTime modifiedDateTime = client.GetLastWriteTime("/test.dat");
Console.WriteLine("Modified date and time of '/test.dat' is: {0}", modifiedDateTime);

// ...

// Disconnect.
client.Disconnect();
' Create a new class instance.
Dim client As New Ftp()

' Connect to the FTP server.
client.Connect("myserver")

' Authenticate.
client.Authenticate("test", "test")

' ...

' Get modified date and time of the remote file '/test.dat'.
Dim modifiedDateTime As Date = client.GetLastWriteTime("/test.dat")
Console.WriteLine("Modified date and time of '/test.dat' is: {0}", modifiedDateTime)

' ...

' Disconnect.
client.Disconnect()
// Create a new class instance.
Ftp client = new Ftp();

// Connect to the FTP server.
client.Connect("myserver");

// Authenticate.
client.Authenticate("userName", "password");

// ...

// Set file permission to OwnerRead + OwnerWrite.
client.SetFilePermissions("/file.dat", FtpFilePermissions.OwnerRead | FtpFilePermissions.OwnerWrite);

// ...

// Disconnect.
client.Disconnect();
' Create a new class instance.
Dim client As New Ftp()

' Connect to the FTP server.
client.Connect("myserver")

' Authenticate.
client.Authenticate("userName", "password")

' ...

' Set file permission to OwnerRead + OwnerWrite.
client.SetFilePermissions("/file.dat", FtpFilePermissions.OwnerRead Or FtpFilePermissions.OwnerWrite)

' ...

' Disconnect.
client.Disconnect()

File permissions

Ftp class exposes flexible event-driven methods to process remote files and directories like uploading, downloading, setting file attributes, etc. By using the SetFilePermissions method, you can set permissions of a single file. The following code snippet shows you how to set permissions of a single file.

Create an empty remote file

To create a new empty file, create an instance of the FtpFileInfo class and call the Create method of that object.

// Create a new class instance.
using (Ftp client = new Ftp())
{
    // Connect to the FTP server.
    client.Connect("localhost");
    // Authenticate.
    client.Authenticate("test", "test");

    FileInfoBase info = client.CreateFileInfo("/newfile", true);
    // Create a new file.
    info.Create();
}
' Create a new class instance.
Using client As New Ftp()
    ' Connect to the FTP server.
    client.Connect("localhost")
    ' Authenticate.
    client.Authenticate("test", "test")

    Dim info As FileInfoBase = client.CreateFileInfo("/newfile", True)
    ' Create a new file.
    info.Create()
End Using

Upload and download multiple files

With a single line of code, you can transfer multiple files at once. Ultimate FTP allows using file masks as parameter for multi-file operations such as upload, download, delete, move, and set permissions. The library also let you transfer files simultaneously using multiple threads.

File masks

File masks consist of three types of symbols and their combinations:

  • Fixed characters: Any letter, number or character that is allowed in a file name. For example, pic.jpg refers to a single file named as ‘pic.jpg’.
  • Question Mark (?): A question mark (?) denotes any single character. For example, ?in.docx can refer to every file with a name consisting of three letters ending with ‘in’ and .docx as an extension like tin.docx, kin.docx, fin.docx, etc.
  • Asterisk (): An asterisk refers to various characters of an indefinite number. For example, at.docx can refer to all .docx files with a name starting with ‘a’ and ending with ‘t’ and can contain any number of characters in between like at.docx, ant.docx, aunt.docx, etc.

'**' is the special wildcard that is used to match any character, including directory separators. See this for more details. The above examples show that a file mask with only fixed characters refers to a single unique file (e.g. file mask my-picture.jpg refers to, and only to, a file named my-picture.jpg), while file masks containing wildcards such as ‘?’ or/and ‘*’ can refer to both single or multiple files.

// Upload files starting with 'best'.
client.Upload(@"C:\Test", "/", new NameSearchCondition("best*"));
' Upload files starting with 'best'.
client.Upload("C:\Test", "/", New NameSearchCondition("best*"))
// Create a new class instance.
Ftp client = new Ftp();

// Connect to the FTP server.
client.Connect("localhost");

// Authenticate.
client.Authenticate("test", "test");

// ...

// Upload all files and subdirectories from local folder 'c:\temp' to the remote dir '/temp'
client.Upload("c:\\temp", "/temp");

// Upload all directories, subdirectories, and files that match the specified search pattern from local folder 'c:\myfolder2' to remote folder '/myfolder2'.
client.Upload("c:\\myfolder2", "/myfolder2", "*.cs");

// or you can simply put wildcard masks in the source path, our component will automatically parse it.
// upload all *.css files from local folder 'c:\myfolder2' to remote folder '/myfolder2'.
client.Upload("c:\\myfolder2\\*.css", "/myfolder2");

// Upload *.cs and *.vb files from local folder 'c:\myfolder2' to remote folder '/myfolder2'.
client.Upload("c:\\myfolder2\\*.cs;*.vb", "/myfolder2");

// ...

// Disconnect.
client.Disconnect();
' Create a new class instance.
Dim client As New Ftp()

' Connect to the FTP server.
client.Connect("localhost")

' Authenticate.
client.Authenticate("test", "test")

' ...

' Upload all files and subdirectories from local folder 'c:\temp' to the remote dir '/temp'
client.Upload("c:\temp", "/temp")

' Upload all directories, subdirectories, and files that match the specified search pattern from local folder 'c:\myfolder2' to remote folder '/myfolder2'.
client.Upload("c:\myfolder2", "/myfolder2", "*.cs")

' or you can simply put wildcard masks in the source path, our component will automatically parse it.
' upload all *.css files from local folder 'c:\myfolder2' to remote folder '/myfolder2'.
client.Upload("c:\myfolder2\*.css", "/myfolder2")

' Upload *.cs and *.vb files from local folder 'c:\myfolder2' to remote folder '/myfolder2'.
client.Upload("c:\myfolder2\*.cs;*.vb", "/myfolder2")

' ...

' Disconnect.
client.Disconnect()

Upload files

To upload multiple files (e.g. all ".dat" files), use the Upload methods. The most used Upload method overload just needs two parameters. The first one is the path to the local directory and the second one is the path to the remote directory.

Download remote files

To download multiple remote files (e.g. all ".dat" files), use the Download methods. The most used Download method overload just needs two parameters. The first one is the path to the remote directory and the second one is the path to the local directory.

// Create a new class instance.
Ftp client = new Ftp();

// Connect to the FTP server.
client.Connect("myserver");

// Authenticate.
client.Authenticate("userName", "password");

// ...

// Get all directories, subdirectories, and files from remote folder '/myfolder' to 'c:\myfolder'.
client.Download("/myfolder", "c:\\myfolder");

// Get all directories, subdirectories, and files that match the specified search pattern from remote folder '/myfolder2' to 'c:\myfolder2'.
client.Download("/myfolder2", "c:\\myfolder2", "*.cs");

// or you can simply put wildcard masks in the source path, our component will automatically parse it.
// download all *.css files from remote folder '/myfolder2' to local folder 'c:\myfolder2'.
client.Download("/myfolder2/*.css", "c:\\myfolder2");

// Download *.cs and *.vb files from remote folder '/myfolder2' to local folder 'c:\myfolder2'.
client.Download("/myfolder2/*.cs;*.vb", "c:\\myfolder2");

// Get files in the folder '/myfolder2' only.
TransferOptions opt = new TransferOptions(true, false, OptionValue.Auto, null, FileOverwriteMode.Overwrite, SymlinksResolveAction.Skip);
client.Download("/myfolder2", "c:\\myfolder2", opt);

// ...

// Disconnect.
client.Disconnect();
' Create a new class instance.
Dim client As New Ftp()

' Connect to the FTP server.
client.Connect("myserver")

' Authenticate.
client.Authenticate("userName", "password")

' ...

' Get all directories, subdirectories, and files from remote folder '/myfolder' to 'c:\myfolder'.
client.Download("/myfolder", "c:\myfolder")

' Get all directories, subdirectories, and files that match the specified search pattern from remote folder '/myfolder2' to 'c:\myfolder2'.
client.Download("/myfolder2", "c:\myfolder2", "*.cs")

' or you can simply put wildcard masks in the source path, our component will automatically parse it.
' download all *.css files from remote folder '/myfolder2' to local folder 'c:\myfolder2'.
client.Download("/myfolder2/*.css", "c:\myfolder2")

' Download *.cs and *.vb files from remote folder '/myfolder2' to local folder 'c:\myfolder2'.
client.Download("/myfolder2/*.cs;*.vb", "c:\myfolder2")

' Get files in the folder '/myfolder2' only.
Dim opt As New TransferOptions(True, False, OptionValue.Auto, Nothing, FileOverwriteMode.Overwrite, SymlinksResolveAction.Skip)
client.Download("/myfolder2", "c:\myfolder2", opt)

' ...

' Disconnect.
client.Disconnect()
private static Ftp _client;
static void Main()
{
    // Create a new class instance.
    Ftp client = new Ftp();
    _client = client;

    // Connect to the FTP server.
    client.Connect("demo.componentpro.com");

    // Authenticate.
    client.Authenticate("test", "test");
    // End Login

    // ...
    client.TransferConfirm += client_TransferConfirm;
    client.Progress += client_Progress;

    try
    {
        TransferOptions opt = new TransferOptions("*.*", FileOverwriteMode.Confirm);

        // Get all directories, subdirectories, and files in local folder 'c:\myfolder' to remote folder '/myfolder'.
        client.Upload("c:\\myfolder", "/myfolder", opt);
    }
    catch (Exception exc)
    {
        Console.WriteLine("Error: " + exc.Message);
    }
    // ...

    // Disconnect.
    client.Disconnect();
}

/// <summary>
/// This method is raised when user clicks on 'Cancel' button on the form.
/// </summary>
protected static void btnCancel_Click(object sender, EventArgs e)
{
    // Cancel the upload operation when user clicks on the button.
    _client.Cancel();
}

static void client_Progress(object sender, ComponentPro.IO.FileSystemProgressEventArgs e)
{
    // Show progress info.
    Console.WriteLine("Current File: %{0} completed", e.Percentage);
    Console.WriteLine("Total: %{0} completed", e.TotalPercentage);

    switch (e.State)
    {
        case TransferState.StartUploadingFile:
            if (e.SourcePath.EndsWith(".exe"))
            {
                // Skip all .exe files
                e.Skip = true;
            }
            else if (e.SourcePath.StartsWith(@"C:\MyFolder"))
            {
                // Change the source file path if it starts with "C:\MyFolder"
                e.SourcePath = e.SourcePath.Replace(@"C:\MyFolder", @"C:\MySecondFolder");
            }
            break;
    }
}

static void client_TransferConfirm(object sender, ComponentPro.IO.TransferConfirmEventArgs e)
{
    if (e.Exception != null)
        Console.WriteLine("Error: " + e.Exception.Message);

    if (e.ConfirmReason == TransferConfirmReason.FileAlreadyExists)
    {
        // Skip the existing file.
        e.NextAction = TransferConfirmNextActions.Skip;
    }

    Console.Write("Do you want to (r)etry or (s)kip?");
    string key = Console.ReadLine();
    if (key == "r")
        e.NextAction = TransferConfirmNextActions.Retry;
    else if (key == "s")
        e.NextAction = TransferConfirmNextActions.Skip;
    else
        // Cancel the operation.
        e.NextAction = TransferConfirmNextActions.Cancel;
}
Private Shared _client As Ftp
Shared Sub Main()
    ' Create a new class instance.
    Dim client As New Ftp()
    _client = client

    ' Connect to the FTP server.
    client.Connect("demo.componentpro.com")

    ' Authenticate.
    client.Authenticate("test", "test")
    ' End Login

    ' ...
    AddHandler client.TransferConfirm, AddressOf client_TransferConfirm
    AddHandler client.Progress, AddressOf client_Progress

    Try
        Dim opt As New TransferOptions("*.*", FileOverwriteMode.Confirm)

        ' Get all directories, subdirectories, and files in local folder 'c:\myfolder' to remote folder '/myfolder'.
        client.Upload("c:\myfolder", "/myfolder", opt)
    Catch exc As Exception
        Console.WriteLine("Error: " & exc.Message)
    End Try
    ' ...

    ' Disconnect.
    client.Disconnect()
End Sub

''' <summary>
''' This method is raised when user clicks on 'Cancel' button on the form.
''' </summary>
Protected Shared Sub btnCancel_Click(ByVal sender As Object, ByVal e As EventArgs)
    ' Cancel the upload operation when user clicks on the button.
    _client.Cancel()
End Sub

Private Shared Sub client_Progress(ByVal sender As Object, ByVal e As ComponentPro.IO.FileSystemProgressEventArgs)
    ' Show progress info.
    Console.WriteLine("Current File: %{0} completed", e.Percentage)
    Console.WriteLine("Total: %{0} completed", e.TotalPercentage)

    Select Case e.State
        Case TransferState.StartUploadingFile
            If e.SourcePath.EndsWith(".exe") Then
                ' Skip all .exe files
                e.Skip = True
            ElseIf e.SourcePath.StartsWith("C:\MyFolder") Then
                ' Change the source file path if it starts with "C:\MyFolder"
                e.SourcePath = e.SourcePath.Replace("C:\MyFolder", "C:\MySecondFolder")
            End If
    End Select
End Sub

Private Shared Sub client_TransferConfirm(ByVal sender As Object, ByVal e As ComponentPro.IO.TransferConfirmEventArgs)
    If e.Exception IsNot Nothing Then
        Console.WriteLine("Error: " & e.Exception.Message)
    End If

    If e.ConfirmReason = TransferConfirmReason.FileAlreadyExists Then
        ' Skip the existing file.
        e.NextAction = TransferConfirmNextActions.Skip
    End If

    Console.Write("Do you want to (r)etry or (s)kip?")
    Dim key As String = Console.ReadLine()
    If key = "r" Then
        e.NextAction = TransferConfirmNextActions.Retry
    ElseIf key = "s" Then
        e.NextAction = TransferConfirmNextActions.Skip
    Else
        ' Cancel the operation.
        e.NextAction = TransferConfirmNextActions.Cancel
    End If
End Sub

Detect issues and react while transferring files

The TransferConfirm and Progress events of the Ftp class give you the ease of controlling files to upload and showing progress while transferring data. The following example illustrates how to register event handlers to the TransferConfirm and Progress events to monitor the file upload process.

Upload/download files with advanced filters

To limit the files that will be uploaded, you can add filtering masks to the localDirectoryPath parameter of the Upload method. However, when you want to exclude unwanted files and directories, you need to use the SearchCondition class or its Fluent API.

client.Upload("c:\\mydata", "/data", new NameSearchCondition("*.txt") - new NameSearchCondition("file*"));

// or
client.Upload("c:\\mydata", "/data", new NameSearchCondition("*.txt").ExcludeMasks("file*"));
client.Upload("c:\mydata", "/data", New NameSearchCondition("*.txt") - New NameSearchCondition("file*"))

' or
client.Upload("c:\mydata", "/data", (New NameSearchCondition("*.txt")).ExcludeMasks("file*"))
// All files in "C:\data" will be copied to "/data" without keeping their directory structure.
TransferOptions opt = new TransferOptions();
opt.Flatten = true;
// Upload files.
client.Upload(@"C:\data", "/data", opt);

// All files in "C:\A" and "C:\B" will be uploaded to "/mydata" without keeping their directory structure.
client.Upload(new string[] {@"C:\A", @"C:\B"}, "/mydata", opt);
' All files in "C:\data" will be copied to "/data" without keeping their directory structure.
Dim opt As New TransferOptions()
opt.Flatten = True
' Upload files.
client.Upload("C:\data", "/data", opt)

' All files in "C:\A" and "C:\B" will be uploaded to "/mydata" without keeping their directory structure.
client.Upload(New String() {"C:\A", "C:\B"}, "/mydata", opt)

Upload/download files without keeping directory structure - flatten mode

The TransferOptions class can even be used to upload (or download) files from multiple directories (or even a whole directory tree) into a single directory - just set the Flatten property to true and call the Upload or Download method. For example, when uploading files "C:\A\a.txt" and "C:\B\b.txt" to "/MyData" directory, both the files end up in the "/MyData" directory (and no "A" or "B" directories are created).

Download remote files simultaneously

Downloading files and directories from the remote FTP server to the local disk is quite simple. All that needs to occur is passing appropriate server information such as hostname, port, username, password/private key and the number of threads to the Download method of the Ftp class.

The following steps illustrate how to use the Download to download files and directories.

static void Main()
{
    // Create a new class instance.
    Ftp client = new Ftp();

    // Connect to the server.
    client.Connect("server");

    // Authenticate.
    client.Authenticate("user", "pass");

    client.CommandResponse += client_ResponseRead;

    // You can register the ThreadStateChanged event here or in the client_Progress event handler as shown below.
    client.ThreadStateChanged += Thread_StateChanged;
    client.Progress += client_Progress;

    // ...

    // Download files and subdirectories from "/my folder" to "c:\\my folder" using 3 threads. This waits untils these threads complete.
    client.Download("/my folder", "c:\\my folder", 3, true);

    // ...

    client.Disconnect();
}

static void client_Progress(object sender, FileSystemProgressEventArgs e)
{
    // You can access the threads used for the multi-thread file operation here.
    // Uncomment the following code to register the StateChanged event of each thread.
    //if (e.State == TransferState.DirectoryStructureBuilt)
    //{
    //    for (int i = 0; i < e.TransferStatistics.Threads.Count; i++)
    //    {
    //        e.TransferStatistics.Threads[i].StateChanged += Thread_StateChanged;
    //    }
    //}

    // When the multi-thread operation completes the status is MultiFileOperationCompleted.
    if (e.State == TransferState.MultiFileOperationCompleted)
        Console.WriteLine("File transfer completed");
}

static long _threadsCompleted;
static void Thread_StateChanged(object sender, TransferThreadStateChangedEventArgs e)
{
    if (e.State == TransferThreadState.Stopped) // The thread is stopped
    {
        TransferThreadInfo info = (TransferThreadInfo)sender;

        Console.WriteLine(string.Format("Thread ID {0} completed", info.ThreadId));

        Interlocked.Increment(ref _threadsCompleted);
        if (Interlocked.Read(ref _threadsCompleted) == 3)
        {
            Console.WriteLine("Multi-threads file transfer completed");
        }
    }
}

static void client_ResponseRead(object sender, CommandResponseEventArgs e)
{
    Ftp client = (Ftp)sender;

    if (client.ThreadId >= 0)
        if (e.Command != null)
            Console.WriteLine("Thread: {0} - CMD>       {1}", client.ThreadId,
                e.Command);
        else
            Console.WriteLine("Thread: {0} - RESPONSE>  {1}", client.ThreadId,
                e.Response);
}
Shared Sub Main()
    ' Create a new class instance.
    Dim client As New Ftp()

    ' Connect to the server.
    client.Connect("server")

    ' Authenticate.
    client.Authenticate("user", "pass")

    AddHandler client.CommandResponse, AddressOf client_ResponseRead

    ' You can register the ThreadStateChanged event here or in the client_Progress event handler as shown below.
    AddHandler client.ThreadStateChanged, AddressOf Thread_StateChanged
    AddHandler client.Progress, AddressOf client_Progress

    ' ...

    ' Download files and subdirectories from "/my folder" to "c:\\my folder" using 3 threads. This waits untils these threads complete.
    client.Download("/my folder", "c:\my folder", 3, True)

    ' ...

    client.Disconnect()
End Sub

Private Shared Sub client_Progress(ByVal sender As Object, ByVal e As FileSystemProgressEventArgs)
    ' You can access the threads used for the multi-thread file operation here.
    ' Uncomment the following code to register the StateChanged event of each thread.
    'if (e.State == TransferState.DirectoryStructureBuilt)
    '{
    '    for (int i = 0; i < e.TransferStatistics.Threads.Count; i++)
    '    {
    '        e.TransferStatistics.Threads[i].StateChanged += Thread_StateChanged;
    '    }
    '}

    ' When the multi-thread operation completes the status is MultiFileOperationCompleted.
    If e.State = TransferState.MultiFileOperationCompleted Then
        Console.WriteLine("File transfer completed")
    End If
End Sub

Private Shared _threadsCompleted As Long
Private Shared Sub Thread_StateChanged(ByVal sender As Object, ByVal e As TransferThreadStateChangedEventArgs)
    If e.State = TransferThreadState.Stopped Then ' The thread is stopped
        Dim info As TransferThreadInfo = CType(sender, TransferThreadInfo)

        Console.WriteLine(String.Format("Thread ID {0} completed", info.ThreadId))

        Interlocked.Increment(_threadsCompleted)
        If Interlocked.Read(_threadsCompleted) = 3 Then
            Console.WriteLine("Multi-threads file transfer completed")
        End If
    End If
End Sub

Private Shared Sub client_ResponseRead(ByVal sender As Object, ByVal e As CommandResponseEventArgs)
    Dim client As Ftp = CType(sender, Ftp)

    If client.ThreadId >= 0 Then
        If e.Command IsNot Nothing Then
            Console.WriteLine("Thread: {0} - CMD>       {1}", client.ThreadId, e.Command)
        Else
            Console.WriteLine("Thread: {0} - RESPONSE>  {1}", client.ThreadId, e.Response)
        End If
    End If
End Sub
// Upload "*.dat" files from "C:\data" to "/content" remote directory on the FTP server.
// Existing files will be skipped.
FileSystemTransferStatistics stat = client.Upload(@"C:\data\*.dat", "/content", false, FileOverwriteMode.Skip);

Console.WriteLine("Total files: {0}. Total dirs: {1}", stat.TotalFiles, stat.TotalDirectories);
Console.WriteLine("Total files skipped: {0}", stat.FilesSkipped);
Console.WriteLine("Total size: {0}", stat.TotalBytes);
' Upload "*.dat" files from "C:\data" to "/content" remote directory on the FTP server.
' Existing files will be skipped.
Dim stat As FileSystemTransferStatistics = client.Upload("C:\data\*.dat", "/content", False, FileOverwriteMode.Skip)

Console.WriteLine("Total files: {0}. Total dirs: {1}", stat.TotalFiles, stat.TotalDirectories)
Console.WriteLine("Total files skipped: {0}", stat.FilesSkipped)
Console.WriteLine("Total size: {0}", stat.TotalBytes)

Transfer statistics

The result of a multiple file operation can be accessed through a FileSystemTransferStatistics object. It provides useful information shown below:

  • FilesProcessed/DirectoriesProcessed - The number of files/directories processed
  • FilesSkipped/DirectoriesSkipped - The number of files/directories skipped
  • TotalFiles/TotalDirectories - The total number of files/directories
  • TotalBytes, TotalBytesSkipped, TotalBytesTransferred - The total number of bytes, skipped bytes, and processed bytes
  • BytesPerSecond - Bytes per second
  • FileList - List of files and directories (available only when TransferOptions.RetainFileList is true)

Automatic ASCII file type classification

By default, the data is transferred in binary mode without any processing. However, when transferring text data between platforms which use different end-of-line sequences (Windows use <CR><LF>, Unix uses <LF>), it's essential to have the sequences automatically converted by setting the transfer mode to ASCII.

In a multi-file transfer, to determine whether a file should be transferred in ASCII or Binary mode, Ultimate FTP uses the AsciiFileSearchConditions property to check against the processing file. If a file matches that criteria, the file will be transferred in ASCII mode; otherwise, binary mode is used.

client.AsciiFileSearchConditions = new SearchCondition[] { new NameSearchCondition("*.txt") };
// Upload TXT files.
// TXT will be transferred in ASCII mode, all other files will be transferred in Binary mode
client.Upload(@"c:\data\*.txt", "/data");
client.AsciiFileSearchConditions = New SearchCondition() { New NameSearchCondition("*.txt") }
' Upload TXT files.
' TXT will be transferred in ASCII mode, all other files will be transferred in Binary mode
client.Upload("c:\data\*.txt", "/data")
// File time will be restored after a transfer.
client.RestoreFileProperties = true;
// Upload DOC files.
client.Upload(@"c:\data\*.doc", "/data");
' File time will be restored after a transfer.
client.RestoreFileProperties = True
' Upload DOC files.
client.Upload("c:\data\*.doc", "/data")

Restore file date and time after transfer

By default, Ultimate FTP does not synchronize creation, last access and last write time of a file or directory after uploading or downloading. To enable file time synchronization, set the RestoreFileProperties to true.

Resume interrupted transfers

When a transfer is interrupted due to a disconnected connection or user abortion, files that are still in transfer progress may be incomplete. Instead of transferring them all again, you can resume transferring the missing parts of the incomplete files only. By specifying FileOverwriteMode.ResumeFileTransfer as the action on existing files, the Upload and Download methods can do this automatically. The library will do the following:

  • Transfer files that are not present in the destination directory.
  • Resume transfer incomplete destination files which have a smaller size than on the source ones.
  • Ignore/skip all files that similar name and size.
// Create a new instance of the Ftp class.
using (Ftp client = new Ftp())
{
    // Connect to the server.
    client.Connect(serverName);

    // Authenticate the user
    client.Authenticate(userName, password);

    // Resume upload files.
    client.Upload(@"c:\data", "/data", true, FileOverwriteMode.ResumeFileTransfer);

    // Resume download "*.dat" and "*.txt" files.
    client.Download("/data/*.dat;*.txt", @"c:\data", true, FileOverwriteMode.ResumeFileTransfer);
}
' Create a new instance of the Sftp class.
Using client As New Ftp()
    ' Connect to the server.
    client.Connect(serverName)

    ' Authenticate the user
    client.Authenticate(userName, password)

    ' Resume upload files.
    client.Upload("c:\data", "/data", True, FileOverwriteMode.ResumeFileTransfer)

    ' Resume download "*.dat" and "*.txt" files.
    client.Download("/data/*.dat;*.txt", "c:\data", True, FileOverwriteMode.ResumeFileTransfer)
End Using
using (Ftp client = new Ftp())
{
    // Connect to the FTP server.
    client.Connect("localhost");

    // Authenticate.
    client.Authenticate("test", "test");

    // Download "data" directory from the server.
    // The local dir "c:\temp" will contain "data" folder
    client.Download("/data/", @"c:\temp");
}
Using client As New Ftp()
    ' Connect to the FTP server.
    client.Connect("localhost")

    ' Authenticate.
    client.Authenticate("test", "test")

    ' Download "data" directory from the server.
    ' The local dir "c:\temp" will contain "data" folder
    client.Download("/data/", "c:\temp")
End Using

Download an entire remote directory

To download an entire remote directory, pass the path to the directory ending with '/' to the Download method.

Upload an entire local directory

To upload an entire directory, pass the path to the directory ending with '\' to the Upload method.

using (Ftp client = new Ftp())
{
    // Connect to the FTP server.
    client.Connect("localhost");

    // Authenticate.
    client.Authenticate("test", "test");

    // Upload "data" directory to the server.
    // The remote dir "/" will contain "/data" folder
    client.Upload(@"c:\data\", "/");
}
Using client As New Ftp()
    ' Connect to the FTP server.
    client.Connect("localhost")

    ' Authenticate.
    client.Authenticate("test", "test")

    ' Upload "data" directory to the server.
    ' The remote dir "/" will contain "/data" folder
    client.Upload("c:\data\", "/")
End Using
using (Ftp client = new Ftp())
{
    // Connect to the FTP server.
    client.Connect("localhost");

    // Authenticate.
    client.Authenticate("test", "test");

    FileInfoBase masterFolder = client.CreateFileInfo("/myfolder", false);
    FileInfoBase targetFolder1 = DiskFileSystem.Default.CreateFileInfo(@"C:\temp\folder1", false);
    FileInfoBase targetFolder2 = DiskFileSystem.Default.CreateFileInfo(@"C:\temp\folder2", false);

    Synchronizer sync = new Synchronizer();
    SyncOptions opt = new SyncOptions();
    opt.AutoConflictResolution = true;
    opt.AllowCreations = true;
    opt.AllowDeletions = false; // Dont allow deletions.
    opt.TimeResolution = TimeResolution.Seconds;

    // Set the Time zone offset between the FTP server and the client
    // Let assume that the time offset is 12 hours. 
    // or you can call client.GetServerTimeDifference() to get the time difference.
    client.ServerTimeZoneOffset = new TimeSpan(0, 12, 0, 0);

    // Synchronize directories.
    sync.Synchronize(masterFolder, opt, null, masterFolder, targetFolder1, targetFolder2);
}
Using client As New Ftp()
    ' Connect to the FTP server.
    client.Connect("localhost")

    ' Authenticate.
    client.Authenticate("test", "test")

    Dim masterFolder As FileInfoBase = client.CreateFileInfo("/myfolder", False)
    Dim targetFolder1 As FileInfoBase = DiskFileSystem.Default.CreateFileInfo("C:\temp\folder1", False)
    Dim targetFolder2 As FileInfoBase = DiskFileSystem.Default.CreateFileInfo("C:\temp\folder2", False)

    Dim sync As New Synchronizer()
    Dim opt As New SyncOptions()
    opt.AutoConflictResolution = True
    opt.AllowCreations = True
    opt.AllowDeletions = False ' Dont allow deletions.
    opt.TimeResolution = TimeResolution.Seconds

    ' Set the Time zone offset between the FTP server and the client
    ' Let assume that the time offset is 12 hours. 
    ' or you can call client.GetServerTimeDifference() to get the time difference.
    client.ServerTimeZoneOffset = New TimeSpan(0, 12, 0, 0)

    ' Synchronize directories.
    sync.Synchronize(masterFolder, opt, Nothing, masterFolder, targetFolder1, targetFolder2)
End Using

2-way files and folders synchronization

To synchronize directories, you can follow the steps below:

  • Creates references to the directories that will be synchronized
  • Create a new instance of the Synchronizer class
  • Call the Synchronize method

The following example demonstrates how to synchronize directories on an FTP server with the local directories. Files within the directories will be synchronized with the most recent version of the correspondingly named file.

Mirror files and directories (1-way synchronization)

In addition to supporting standard file transfer methods, the Ultimate FTP component also offers a set of easy-to-use methods to mirror folders. To mirror a local folder with a remote folder, call the QuickSynchronize method of the Ftp.

The following steps show you how to use the QuickSynchronize method to synchronize a remote folder with a local folder.

Ftp client = new Ftp();

// Connect to the FTP server.
client.Connect("myserver", 21);

// Authenticate.
client.Authenticate("userName", "password");

// Create a new instance of the MirrorOptions class.
QuickSyncOptions opt = new QuickSyncOptions();

// Set synchronization's settings
opt.Comparer = FileComparers.FileContentComparer;
opt.Recursive = true;

// Synchronize folders.
client.QuickSynchronize(
    "/", // Source directory.
    "c:\\test", // Destination directory. This local dir will be identical to the remote dir ('/').
    true, // Remote dir is master
    opt
    );

// Do something here
// ...

client.Disconnect();
Dim client As New Ftp()

' Connect to the FTP server.
client.Connect("myserver", 21)

' Authenticate.
client.Authenticate("userName", "password")

' Create a new instance of the MirrorOptions class.
Dim opt As New QuickSyncOptions()

' Set synchronization's settings
opt.Comparer = FileComparers.FileContentComparer
opt.Recursive = True

' Synchronize folders.
client.QuickSynchronize("/", "c:\test", True, opt) ' Remote dir is master -  Destination directory. This local dir will be identical to the remote dir ('/'). -  Source directory.

' Do something here
' ...

client.Disconnect()
private static void Main()
{
    // Create a new Ftp instance.
    Ftp client = new Ftp();

    // Connect to the FTP server.
    client.Connect("demo.componentpro.com");

    // Authenticate.
    client.Authenticate("test", "test");

    try
    {
        // Register an event handler.
        client.Progress += client_Progress;

        // Upload file "c:\test.zip".
        client.UploadFile("c:\\test.zip", "test.zip");
    }
    catch (FtpException exc)
    {
        Console.WriteLine("Exception: " + exc.Message);
    }

    // Disconnect.
    client.Disconnect();
}

private static void client_Progress(object sender, FileSystemProgressEventArgs e)
{
    // Abort the uploading operation if the bytes transferred is greater than or equal to 500Kb.
    if (e.State == TransferState.Uploading && e.BytesTransferred >= 1024*500)
    {
        ((Ftp) sender).Cancel();
    }
}

Public Shared Sub Main()
    ' Create a new Ftp instance.
    Dim client As New Ftp()

    ' Connect to the FTP server.
    client.Connect("demo.componentpro.com")

    ' Authenticate.
    client.Authenticate("test", "test")

    Try
        ' Register an event handler.
        AddHandler client.Progress, AddressOf client_Progress

        ' Upload file "c:\test.zip".
        client.UploadFile("c:\test.zip", "test.zip")
    Catch exc As FtpException
        Console.WriteLine("Exception: " & exc.Message)
    End Try

    ' Disconnect.
    client.Disconnect()
End Sub

Private Shared Sub client_Progress(ByVal sender As Object, ByVal e As FileSystemProgressEventArgs)
    ' Abort the uploading operation if the bytes transferred is greater than or equal to 500Kb.
    If e.State = TransferState.Uploading AndAlso e.BytesTransferred >= 1024*500 Then
        CType(sender, Ftp).Cancel()
    End If
End Sub

Cancel operation

To abort a file transfer that is still in progress, you can either call the Cancel method or close the connection by calling the Disconnect or DisconnectAsync method.

The following code snippet shows how to use it.

Show the progress while transferring data

When the file to transfer is big, or the transfer speed is slow, you can let the user know that your app is transferring files by updating a progress bar. The Ultimate FTP component provides progress notification through the Progress event. The event is raised periodically while data transfer is in progress, making accessible necessary data to display progress information, such as the size of the file and the number of bytes transferred.

The following example shows you how to handle the Progress event to show progress information while transferring a file:

Unable to read code file 'C:\Inetpub\vhosts\componentpro.com\httpdocs\Sites\ComponentPro\CodeExamples\Ftp\CS\GeneralEvent\Progress.cs'.
Unable to read code file 'C:\Inetpub\vhosts\componentpro.com\httpdocs\Sites\ComponentPro\CodeExamples\Ftp\VB\GeneralEvent\Progress.vb'.

Manage multiple remote files and directories

This section shows how to manage multiple remote files and directories like deleting, moving, and setting permissions.

Delete files and directories

To delete multiple files, use the Delete. The methods require the path to the remote directory containing entries to delete as the first parameter. The following illustrates how to use the Delete to delete multiple files.

// Create a new class instance.
Ftp client = new Ftp();

// Connect to the FTP server.
client.Connect("myserver");

// Authenticate.
client.Authenticate("userName", "password");

// ...

// Delete all files in folder /my folder.
client.Delete("/my folder", true, true, null);

// Delete all *.tmp files recursively.
client.Delete("/temp", true, true, new NameSearchCondition("*.tmp"));

// Delete selected files only.
object[] filesToDelete = { "/temp/test.cs", "/test/test.tmp" };
client.Delete(filesToDelete, true, true, null);

// ...

// Disconnect.
client.Disconnect();
' Create a new class instance.
Dim client As New Ftp()

' Connect to the FTP server.
client.Connect("myserver")

' Authenticate.
client.Authenticate("userName", "password")

' ...

' Delete all files in folder /my folder.
client.Delete("/my folder", True, True, Nothing)

' Delete all *.tmp files recursively.
client.Delete("/temp", True, True, New NameSearchCondition("*.tmp"))

' Delete selected files only.
Dim filesToDelete() As Object = { "/temp/test.cs", "/test/test.tmp" }
client.Delete(filesToDelete, True, True, Nothing)

' ...

' Disconnect.
client.Disconnect()
static void Main()
{
    // Create a new class instance.
    Ftp client = new Ftp();

    // Connect to the SFTP server.
    client.Connect("myserver");

    // Authenticate.
    client.Authenticate("userName", "password");

    // ...

    // Move an entire directory with the standard rename command.
    client.Rename("/my old folder", "/my new folder/new one");
    
    TransferOptions opt = new TransferOptions(
        true, // Build directory structure.
        true, // Recursive.
        OptionValue.Yes, // Create empty directories.  
        (SearchCondition)null, // 
        FileOverwriteMode.Overwrite,
        SymlinksResolveAction.Skip);
    opt.DeleteEmptyDirectories = true; // Remove empty directories.            
    // Move all .cs and .vb files to a new folder.
    client.Move("/myfolder2/*.cs,*.vb", "/my new folder", opt);

    // Move the selected files in '/my folder' to 'my new folder'.
    string[] files = { "my file1.dat", "file2.txt", "my dir" };
    client.Move("/my folder", files, "my new folder", opt);

    // Handle file existence event
    client.TransferConfirm += client_TransferConfirm;
    opt.FileOverwriteMode = FileOverwriteMode.Confirm;

    // Move all *.dat and *.txt files to 'my dest' folder.
    // If a .txt file already exists, skip it; otherwise overwrite. See the event handler client_TransferConfirm.
    client.Move("my source/*.dat,*.txt", "my dest", opt);

    // With advanced search conditions.
    opt.SearchCondition =
        SearchCondition.SizeInRange(10, 10240) +        // Search for files with size from 10 -> 10240 bytes
        SearchCondition.ModifiedAfter(new DateTime(2010, 05, 01)); // and modifed after 2010/05/01.
    // Move XLS files.
    client.Move("my data/*.xls", "my dest", opt);

    // Move files simultaneously using 3 threads.
    client.Move("/my root/*.txt", "/new folder", 3, true);

    // ...

    // Disconnect.
    client.Disconnect();
}

static void client_TransferConfirm(object sender, TransferConfirmEventArgs e)
{
    if (e.ConfirmReason == TransferConfirmReason.FileAlreadyExists)
    {
        if (e.SourceFileInfo.Name.EndsWith(".txt"))
            e.NextAction = TransferConfirmNextActions.Skip; // Skip 'txt' file if it already exists.
        else
            e.NextAction = TransferConfirmNextActions.Overwrite; // otherwise overwrite it.
    }
}
Shared Sub Main()
    ' Create a new class instance.
    Dim client As New Ftp()

    ' Connect to the SFTP server.
    client.Connect("myserver")

    ' Authenticate.
    client.Authenticate("userName", "password")

    ' ...

    ' Move an entire directory with the standard rename command.
    client.Rename("/my old folder", "/my new folder/new one")

    Dim opt As New TransferOptions(True, True, OptionValue.Yes, CType(Nothing, SearchCondition), FileOverwriteMode.Overwrite, SymlinksResolveAction.Skip) ' Create empty directories. -  Recursive. -  Build directory structure.
    opt.DeleteEmptyDirectories = True ' Remove empty directories.
    ' Move all .cs and .vb files to a new folder.
    client.Move("/myfolder2/*.cs,*.vb", "/my new folder", opt)

    ' Move the selected files in '/my folder' to 'my new folder'.
    Dim files() As String = { "my file1.dat", "file2.txt", "my dir" }
    client.Move("/my folder", files, "my new folder", opt)

    ' Handle file existence event
    AddHandler client.TransferConfirm, AddressOf client_TransferConfirm
    opt.FileOverwriteMode = FileOverwriteMode.Confirm

    ' Move all *.dat and *.txt files to 'my dest' folder.
    ' If a .txt file already exists, skip it; otherwise overwrite. See the event handler client_TransferConfirm.
    client.Move("my source/*.dat,*.txt", "my dest", opt)

    ' With advanced search conditions.
    opt.SearchCondition = SearchCondition.SizeInRange(10, 10240) + SearchCondition.ModifiedAfter(New Date(2010, 05, 01)) ' and modifed after 2010/05/01. -  Search for files with size from 10 -> 10240 bytes
    ' Move XLS files.
    client.Move("my data/*.xls", "my dest", opt)

    ' Move files simultaneously using 3 threads.
    client.Move("/my root/*.txt", "/new folder", 3, True)

    ' ...

    ' Disconnect.
    client.Disconnect()
End Sub

Private Shared Sub client_TransferConfirm(ByVal sender As Object, ByVal e As TransferConfirmEventArgs)
    If e.ConfirmReason = TransferConfirmReason.FileAlreadyExists Then
        If e.SourceFileInfo.Name.EndsWith(".txt") Then
            e.NextAction = TransferConfirmNextActions.Skip ' Skip 'txt' file if it already exists.
        Else
            e.NextAction = TransferConfirmNextActions.Overwrite ' otherwise overwrite it.
        End If
    End If
End Sub

Move files and directories

To move remote files and directories from one remote directory to another remote directory, use the Move methods. These methods require the path to the remote directory containing files and directories to move and the path of the destination remote directory. There are many advanced options such as moving files and directories recursively, custom search conditions, and custom file comparison.

Control multi-file deletion process

The Progress event of the Ftp class gives you the ease of controlling files to delete. To decide whether a file should be deleted, just handle the Progress event and set the Skip property of the FileSystemProgressEventArgs class to true. The following example illustrates how to do that:

private static Ftp _client;
static void Main()
{
    // Create a new class instance.
    Ftp client = new Ftp();
    _client = client;

    // Connect to the FTP server.
    client.Connect("192.168.126.128", 2222);

    // Authenticate.
    client.Authenticate("test", "test");

    client.Progress += client_Progress;

    // ...

    // Delete *.tmp files
    client.Delete("/", false, true, "*.tmp");
    
    // ...

    // Disconnect.
    client.Disconnect();
}

static void client_Progress(object sender, ComponentPro.IO.FileSystemProgressEventArgs e)
{
    if (e.State == TransferState.DeletingFile)
    {
        // Skip file that its name contains "my file" text.
        if (e.SourcePath.IndexOf("my file") != -1)
            e.Skip = true;
    }
}

/// <summary>
/// This method is raised when user clicks on 'Cancel' button on the form.
/// </summary>
protected void btnCancel_Click(object sender, EventArgs e)
{
    // Cancel the deleting operation when user clicks on the button.
    _client.Cancel();
}
Private Shared _client As Ftp
Shared Sub Main()
    ' Create a new class instance.
    Dim client As New Ftp()
    _client = client

    ' Connect to the FTP server.
    client.Connect("192.168.126.128", 2222)

    ' Authenticate.
    client.Authenticate("test", "test")

    AddHandler client.Progress, AddressOf client_Progress

    ' ...

    ' Delete *.tmp files
    client.Delete("/", False, True, "*.tmp")

    ' ...

    ' Disconnect.
    client.Disconnect()
End Sub

Private Shared Sub client_Progress(ByVal sender As Object, ByVal e As ComponentPro.IO.FileSystemProgressEventArgs)
    If e.State = TransferState.DeletingFile Then
        ' Skip file that its name contains "my file" text.
        If e.SourcePath.IndexOf("my file") <> -1 Then
            e.Skip = True
        End If
    End If
End Sub

''' <summary>
''' This method is raised when user clicks on 'Cancel' button on the form.
''' </summary>
Protected Sub btnCancel_Click(ByVal sender As Object, ByVal e As EventArgs)
    ' Cancel the deleting operation when user clicks on the button.
    _client.Cancel()
End Sub
// Create a new class instance.
Ftp client = new Ftp();

// Connect to the FTP server.
client.Connect("myserver");

// Authenticate.
client.Authenticate("userName", "password");

// ...

// Set files' permissions to OwnerRead + OwnerWrite recursively.
client.SetMultipleFilesPermissions("/", FtpFilePermissions.OwnerRead | FtpFilePermissions.OwnerWrite, true, new NameSearchCondition("*.dat"));

// ...

// Disconnect.
client.Disconnect();
' Create a new class instance.
Dim client As New Ftp()

' Connect to the FTP server.
client.Connect("myserver")

' Authenticate.
client.Authenticate("userName", "password")

' ...

' Set files' permissions to OwnerRead + OwnerWrite recursively.
client.SetMultipleFilesPermissions("/", FtpFilePermissions.OwnerRead Or FtpFilePermissions.OwnerWrite, True, New NameSearchCondition("*.dat"))

' ...

' Disconnect.
client.Disconnect()

Set permissions of multiple files and directories

Ultimate FTP provides both methods for setting permissions of a single file or multiple files. To set permissions of multiple files, use the SetMultipleFilesPermissions method of the Ftp class. The following example shows you how easy it is to set permissions of multiple files.

Manage a remote directory

In addition to supporting standard file transfer methods, the Ultimate FTP component also offers a set of easy-to-use methods to manage remote directories: list folder content, create, rename/move, check existence, delete recursively, and get folder total size.

List directory content

Use the ListDirectory method of Ftp to read the directory contents. The first parameter of that method is the path to the directory. The resulting list returned by the ListDirectory method contains references to instances of FtpFileInfo class. Each instance contains information about a directory entry (file, subdirectory, symlink etc.)

// Create a new class instance.
Ftp client = new Ftp();

// Connect to the FTP server.
client.Connect("myserver");

// Authenticate.
client.Authenticate("test", "test");

// ...

// Get information of all files and directories in '/' remote dir.
foreach (FtpFileInfo info in client.ListDirectory("/"))
{
    Console.WriteLine("Name: {0}, Permissions: {1}", info.Name, info.Permissions);
}

// Many FTP servers do not support ListDirectory with parameter method, Hence, we have to
// change the current directory before calling ListDirectory.
// Get names of all files and directories in '/my folder' remote dir.
client.SetCurrentDirectory("/my folder");
foreach (FtpFileInfo info in client.ListDirectory())
{
    Console.WriteLine("Name: {0}, Permissions: {1}", info.Name, info.Permissions);
}

// List files with search condition.
// List all files that have .exe extension in "/" folder.
foreach (FtpFileInfo info in client.ListDirectory("/", new NameSearchCondition("*.exe")))
{
    Console.WriteLine("Name: {0}, Permissions: {1}", info.Name, info.Permissions);
}

// Change the current directory before calling ListDirectory.
// Get names of files with .cs or .vb extensions and directories in '/my folder2' remote dir.
client.SetCurrentDirectory("/my folder2");
foreach (FtpFileInfo info in client.ListDirectory(new NameSearchCondition("*.cs;*.vb")))
{
    Console.WriteLine("Name: {0}, Permissions: {1}", info.Name, info.Permissions);
}

// ...

// Disconnect.
client.Disconnect();
' Create a new class instance.
Dim client As New Ftp()

' Connect to the FTP server.
client.Connect("myserver")

' Authenticate.
client.Authenticate("test", "test")

' ...

' Get information of all files and directories in '/' remote dir.
For Each info As FtpFileInfo In client.ListDirectory("/")
    Console.WriteLine("Name: {0}, Permissions: {1}", info.Name, info.Permissions)
Next info

' Many FTP servers do not support ListDirectory with parameter method, Hence, we have to
' change the current directory before calling ListDirectory.
' Get names of all files and directories in '/my folder' remote dir.
client.SetCurrentDirectory("/my folder")
For Each info As FtpFileInfo In client.ListDirectory()
    Console.WriteLine("Name: {0}, Permissions: {1}", info.Name, info.Permissions)
Next info

' List files with search condition.
' List all files that have .exe extension in "/" folder.
For Each info As FtpFileInfo In client.ListDirectory("/", New NameSearchCondition("*.exe"))
    Console.WriteLine("Name: {0}, Permissions: {1}", info.Name, info.Permissions)
Next info

' Change the current directory before calling ListDirectory.
' Get names of files with .cs or .vb extensions and directories in '/my folder2' remote dir.
client.SetCurrentDirectory("/my folder2")
For Each info As FtpFileInfo In client.ListDirectory(New NameSearchCondition("*.cs;*.vb"))
    Console.WriteLine("Name: {0}, Permissions: {1}", info.Name, info.Permissions)
Next info

' ...

' Disconnect.
client.Disconnect()
// Create a new class instance.
Ftp client = new Ftp();

// Connect to the FTP server.
client.Connect("localhost");

// Authenticate.
client.Authenticate("test", "test");

// ...

// Get the current directory.
string absolutePath = client.GetCurrentDirectory();
Console.WriteLine("Current directory is '{0}'", absolutePath);

// ...

// Disconnect.
client.Disconnect();
' Create a new class instance.
Dim client As New Ftp()

' Connect to the FTP server.
client.Connect("localhost")

' Authenticate.
client.Authenticate("test", "test")

' ...

' Get the current directory.
Dim absolutePath As String = client.GetCurrentDirectory()
Console.WriteLine("Current directory is '{0}'", absolutePath)

' ...

' Disconnect.
client.Disconnect()

Get and set current working directory

To get the current working directory for the currently logged in user, use GetCurrentDirectory method. To change it, use SetCurrentDirectory method.

Create an empty directory

To create a new directory, call the CreateDirectory method of the Ftp class. By default, a new directory will be created in the current working directory. If you want to create the directory in another location, you could use the SetCurrentDirectory to change the current working directory before calling the CreateDirectory method. The method also accepts an absolute path.

The following code example shows you how to use the CreateDirectory method to create a new directory on the remote FTP server.

// Create a new class instance.
Ftp client = new Ftp();

// Connect to the FTP server.
client.Connect("myserver");

// Authenticate.
client.Authenticate("userName", "password");

// ...

// Create 'myFolder' directory.
client.CreateDirectory("/myFolder");

// ...

// Disconnect.
client.Disconnect();
' Create a new class instance.
Dim client As New Ftp()

' Connect to the FTP server.
client.Connect("myserver")

' Authenticate.
client.Authenticate("userName", "password")

' ...

' Create 'myFolder' directory.
client.CreateDirectory("/myFolder")

' ...

' Disconnect.
client.Disconnect()
// Create a new class instance.
Ftp client = new Ftp();

// Connect to the SFTP server.
client.Connect("server");

// Authenticate.
client.Authenticate("test", "test");

client.EnsuresDirectoryCreated("/home/data/personal/photos/family-photos");

// ...

// Disconnect.
client.Disconnect();
' Create a new class instance.
Dim client As New Ftp()

' Connect to the SFTP server.
client.Connect("server")

' Authenticate.
client.Authenticate("test", "test")

client.EnsuresDirectoryCreated("/home/data/personal/photos/family-photos")

' ...

' Disconnect.
client.Disconnect()

Ensure a directory hierarchy created

When you need to create a directory with path like "/home/data/personal/photos/family-photos", but you are not sure whether "/home/data", "/home/data/personal", or "/home/data/personal/photos" exists. You may end up splitting the path by '/' character and checking the split paths for existence one by one. The FileSystem base class from which the Sftp class inherit has a method EnsuresDirectoryCreated method to help you do so.

Rename/move a directory

To rename a directory, use the Rename method. It also supports moving a remote directory to another location.

// Create a new class instance.
Ftp client = new Ftp();

// Connect to the FTP server.
client.Connect("myserver");

// Authenticate.
client.Authenticate("userName", "password");

// ...

// Rename remote file '/file.dat' to 'myfile.dat'
client.Rename("/file.dat", "/myfile.dat");

// Move a file
client.Rename("/file2.dat", "/new-folder/file2.dat");

// Rename a remote directory
client.Rename("/album-folder", "/old-album-folder");

// Move a directory
client.Rename("/album-folder2", "/new-folder/album-folder2");

// ...

// Disconnect.
client.Disconnect();
' Create a new class instance.
Dim client As New Ftp()

' Connect to the FTP server.
client.Connect("myserver")

' Authenticate.
client.Authenticate("userName", "password")

' ...

' Rename remote file '/file.dat' to 'myfile.dat'
client.Rename("/file.dat", "/myfile.dat")

' Move a file
client.Rename("/file2.dat", "/new-folder/file2.dat")

' Rename a remote directory
client.Rename("/album-folder", "/old-album-folder")

' Move a directory
client.Rename("/album-folder2", "/new-folder/album-folder2")

' ...

' Disconnect.
client.Disconnect()
// Create a new class instance.
Ftp client = new Ftp();

// Connect to the FTP server.
client.Connect("myserver");

// Authenticate.
client.Authenticate("userName", "password");

// ...

// Determine whether folder 'myFolder' exists or not.
if (client.DirectoryExists("/myFolder"))
    Console.WriteLine("Folder '/myFolder' exists");
else
    Console.WriteLine("Folder '/myFolder' does not exist");

// ...

// Disconnect.
client.Disconnect();
' Create a new class instance.
Dim client As New Ftp()

' Connect to the FTP server.
client.Connect("myserver")

' Authenticate.
client.Authenticate("userName", "password")

' ...

' Determine whether folder 'myFolder' exists or not.
If client.DirectoryExists("/myFolder") Then
    Console.WriteLine("Folder '/myFolder' exists")
Else
    Console.WriteLine("Folder '/myFolder' does not exist")
End If

' ...

' Disconnect.
client.Disconnect()

Check directory existence

To determine whether a remote directory exists or not, use the DirectoryExists method. You just need to pass the path of the remote directory to the method, and it returns a boolean value indicating whether the specified directory exists or not.

The following code snippet shows you how to use the DirectoryExists method to determine whether a directory exists or not.

Delete a directory recursively

To delete a non-empty remote directory or multiple files, use the Delete method. If the recursive parameter of the method is passed as true, the method searches for entries in subdirectories as well. Hence, you should use the method with attention.

To delete an empty directory, use the DeleteDirectory method.

// Create a new class instance.
Ftp client = new Ftp();

// Connect to the FTP server.
client.Connect("localhost");

// Authenticate.
client.Authenticate("test", "test");

// ...

// Remove an empty directory.
client.DeleteDirectory("/temp");

// Delete an entire directory.
client.DeleteDirectory("/test", true);

// Delete files with size smaller than 200kb in "/test dir" directory. All empty directories will be removed.
client.Delete("/my folder", true, new SizeSearchCondition(0, 200 * 1024));

// Delete .exe files in "/test dir" directory. All empty directories will be removed.
client.Delete("/test dir", true, "*.exe");

// Delete .tmp and .temp files in "/test dir" directory. All empty directories will be removed.
// wildcard masks are delimited by ';', ',', and '|' characters.
client.Delete("/test dir/*.tmp;*.temp", true);

// Delete .cs files in "/test folder" directory. All empty directories are not to be removed.
client.Delete("/test folder", true, false, new NameSearchCondition(".cs"));

// ...

// Disconnect.
client.Disconnect();
' Create a new class instance.
Dim client As New Ftp()

' Connect to the FTP server.
client.Connect("localhost")

' Authenticate.
client.Authenticate("test", "test")

' ...

' Remove an empty directory.
client.DeleteDirectory("/temp")

' Delete an entire directory.
client.DeleteDirectory("/test", True)

' Delete files with size smaller than 200kb in "/test dir" directory. All empty directories will be removed.
client.Delete("/my folder", True, New SizeSearchCondition(0, 200 * 1024))

' Delete .exe files in "/test dir" directory. All empty directories will be removed.
client.Delete("/test dir", True, "*.exe")

' Delete .tmp and .temp files in "/test dir" directory. All empty directories will be removed.
' wildcard masks are delimited by ';', ',', and '|' characters.
client.Delete("/test dir/*.tmp;*.temp", True)

' Delete .cs files in "/test folder" directory. All empty directories are not to be removed.
client.Delete("/test folder", True, False, New NameSearchCondition(".cs"))

' ...

' Disconnect.
client.Disconnect()
void CalculateDirSize()
{
    // Create a new class instance.
    Ftp client = new Ftp();

    // Connect to the FTP server.
    client.Connect("myserver");

    // Authenticate.
    client.Authenticate("userName", "password");

    // ...

    // Calculate total size of an entire directory.
    long totalSize = client.GetDirectorySize("/myFolder", true, null);
    Console.WriteLine("Calculate total size for all files: " + FormatSize(totalSize));

    // Calculate total size for files with extension .dat.
    totalSize = client.GetDirectorySize("/myFolder", true, "*.dat");
    Console.WriteLine("Calculate total size for all .dat files: " + FormatSize(totalSize));

    // Calculate total size for files that are bigger than 100kb.
    totalSize = client.GetDirectorySize("/myFolder", true, new SizeSearchCondition(100 * 1024, long.MaxValue));
    Console.WriteLine("Total size: " + FormatSize(totalSize));

    // ...

    // Disconnect.
    client.Disconnect();
}

/// <summary>
/// Returns a formatted file size in bytes, kbytes, or mbytes.
/// </summary>
/// <param name="size">The input file size.</param>
/// <returns>The formatted file size.</returns>
public string FormatSize(long size)
{
    if (size < 1024)
        return size + " B";
    if (size < 1024 * 1024)
        return string.Format("{0:#.#} KB", size / 1024.0f);
    return size < 1024 * 1024 * 1024 ? string.Format("{0:#.#} MB", size / 1024.0f / 1024.0f) : string.Format("{0:#.#} GB", size / 1024.0f / 1024.0f / 1024.0f);
}
Private Sub CalculateDirSize()
    ' Create a new class instance.
    Dim client As New Ftp()

    ' Connect to the FTP server.
    client.Connect("myserver")

    ' Authenticate.
    client.Authenticate("userName", "password")

    ' ...

    ' Calculate total size of an entire directory.
    Dim totalSize As Long = client.GetDirectorySize("/myFolder", True, Nothing)
    Console.WriteLine("Calculate total size for all files: " & FormatSize(totalSize))

    ' Calculate total size for files with extension .dat.
    totalSize = client.GetDirectorySize("/myFolder", True, "*.dat")
    Console.WriteLine("Calculate total size for all .dat files: " & FormatSize(totalSize))

    ' Calculate total size for files that are bigger than 100kb.
    totalSize = client.GetDirectorySize("/myFolder", True, New SizeSearchCondition(100 * 1024, Long.MaxValue))
    Console.WriteLine("Total size: " & FormatSize(totalSize))

    ' ...

    ' Disconnect.
    client.Disconnect()
End Sub

''' <summary>
''' Returns a formatted file size in bytes, kbytes, or mbytes.
''' </summary>
''' <param name="size">The input file size.</param>
''' <returns>The formatted file size.</returns>
Public Function FormatSize(ByVal size As Long) As String
    If size < 1024 Then
        Return size & " B"
    End If
    If size < 1024 * 1024 Then
        Return String.Format("{0:#.#} KB", size / 1024.0F)
    End If
    If size < 1024 * 1024 * 1024 Then
        Return String.Format("{0:#.#} MB", size / 1024.0F / 1024.0F)
    Else
        Return String.Format("{0:#.#} GB", size / 1024.0F / 1024.0F / 1024.0F)
    End If
End Function

Get directory size

Use the GetDirectorySize method to calculate the total content size of a directory on the FTP server. The Ftp class automatically does all the hard work such as detecting FTP Server OS, determining the listing type, listing directories, and calculating the total content size.

The following steps show you how to use the GetDirectorySize method to retrieve the total content size of a remote directory in bytes.

Control bandwidth and speed optimization

You can use the MaxUploadSpeed and MaxDownloadSpeed properties to limit the transfer speed of the Ftp class. The class also let you choose optimum option to improve transfer speed. In some cases, setting the Ftp.Config.HighSpeedNetworkOptimization property to true may improve the transfer speed, particularly when downloading. If the property is set to true, TCP socket's receive buffer is set to 4MB, and TCP socket's send buffer is set to 256KB.

Control bandwidth - set speed limits

ComponentPro transport classes (Ftp and Sftp) support so-called bandwidth control - restrictions on the amount of data transferred per second. Bandwidth throttlings are set separately for uploading and downloading data. There are some reasons why an application needs the bandwidth throttling feature.

When the network connection is shared between multiple consumers, high transfer speed is not always desirable. In this situation, it is essential for the application using the component not to consume too much network bandwidth and let other consumers make use of the network as well.

In slow and unstable networks, lower speed of transfer usually increases stability and decreases the chance of network failure and disconnection.

MaxUploadSpeed and MaxDownloadSpeed properties of the Ftp component can be used to adjust transfer speed on the fly.

// Limit max download speed to 10k (1024 * 10 bytes) per second.
client.MaxDownloadSpeed = 10 * 1024;

// Limit max upload speed to 8k (1024 * 8 bytes) per second.
client.MaxDownloadSpeed = 8 * 1024;
' Limit max download speed to 10k (1024 * 10 bytes) per second.
client.MaxDownloadSpeed = 10 * 1024

' Limit max upload speed to 8k (1024 * 8 bytes) per second.
client.MaxDownloadSpeed = 8 * 1024

Events

You can handle the events in the Ftp class to control file transfer and get notified when an event is triggered by the Ftp class.

CertificateRequired event

The CertificateRequired event is triggered when a client certificate is required by the FTP server, or the one provided was not accepted. For more details, visit topic Authenticate with a client certificate.

static void Main()
{
    // Create a new instance of the Ftp class.
    Ftp client = new Ftp();

    client.CertificateRequired += client_CertificateRequired;

    // Connect to the FTP server.
    client.Connect("myserver", 21, SslSecurityMode.Explicit);

    // Authenticate.
    client.Authenticate("userName", "password");

    // Do something here...
    client.DownloadFile("/my remote file.dat", "my local file");

    // Disconnect.
    client.Disconnect();
}

static void client_CertificateRequired(object sender, ComponentPro.Security.CertificateRequiredEventArgs e)
{
    // Load certificates from the local machine.
    X509Store my = new X509Store(StoreName.My, StoreLocation.CurrentUser);
    my.Open(OpenFlags.ReadOnly);

    // Retrieve a list of available certificates.
    X509Certificate2Collection certs = my.Certificates;

    // If no certificate found, return.
    if (certs.Count == 0)
    {
        e.Certificates = null;
        return;
    }

    // Show all certificates.
    Console.WriteLine("Select certificate:");
    for (int i = 0; i <= certs.Count; i++)
    {
        if (i == 0)
        {
            Console.WriteLine(string.Format("{0}. [Nothing, skip this step]", i));
            continue;
        }

        Console.WriteLine(string.Format("{0}. {1}", i, certs[i - 1].SubjectName.Name));
    }

    // And ask user to choose an appropriate certificate.
    while (true)
    {
        Console.Write(string.Format("Select certificate [0 - {0}]: ", certs.Count));

        int certIndex;

        try
        {
            certIndex = int.Parse(Console.ReadLine());
        }
        catch
        {
            Console.WriteLine("ERROR: Wrong certificate index input!");
            continue;
        }

        if (certIndex > 0 && certIndex <= certs.Count)
        {
            e.Certificates = new X509Certificate2Collection(certs[certIndex]);
            return;
        }

        if (certIndex == 0)
            break;

        Console.WriteLine(string.Format("ERROR: You must enter number between 0 and {0}.", certs.Count));
    }
}
Shared Sub Main()
    ' Create a new instance of the Ftp class.
    Dim client As New Ftp()

    AddHandler client.CertificateRequired, AddressOf client_CertificateRequired

    ' Connect to the FTP server.
    client.Connect("myserver", 21, SslSecurityMode.Explicit)

    ' Authenticate.
    client.Authenticate("userName", "password")

    ' Do something here...
    client.DownloadFile("/my remote file.dat", "my local file")

    ' Disconnect.
    client.Disconnect()
End Sub

Private Shared Sub client_CertificateRequired(ByVal sender As Object, ByVal e As ComponentPro.Security.CertificateRequiredEventArgs)
    ' Load certificates from the local machine.
    Dim my As New X509Store(StoreName.My, StoreLocation.CurrentUser)
    my.Open(OpenFlags.ReadOnly)

    ' Retrieve a list of available certificates.
    Dim certs As X509Certificate2Collection = my.Certificates

    ' If no certificate found, return.
    If certs.Count = 0 Then
        e.Certificates = Nothing
        Return
    End If

    ' Show all certificates.
    Console.WriteLine("Select certificate:")
    For i As Integer = 0 To certs.Count
        If i = 0 Then
            Console.WriteLine(String.Format("{0}. [Nothing, skip this step]", i))
            Continue For
        End If

        Console.WriteLine(String.Format("{0}. {1}", i, certs(i - 1).SubjectName.Name))
    Next i

    ' And ask user to choose an appropriate certificate.
    Do
        Console.Write(String.Format("Select certificate [0 - {0}]: ", certs.Count))

        Dim certIndex As Integer

        Try
            certIndex = Integer.Parse(Console.ReadLine())
        Catch
            Console.WriteLine("ERROR: Wrong certificate index input!")
            Continue Do
        End Try

        If certIndex > 0 AndAlso certIndex <= certs.Count Then
            e.Certificates = New X509Certificate2Collection(certs(certIndex))
            Return
        End If

        If certIndex = 0 Then
            Exit Do
        End If

        Console.WriteLine(String.Format("ERROR: You must enter number between 0 and {0}.", certs.Count))
    Loop
End Sub
static void Main()
{
    // Create a new class instance.
    Ftp client = new Ftp();

    client.CertificateReceived += client_CertificateReceived;

    // Connect to the FTP server.
    client.Connect("myserver", 21, SslSecurityMode.Explicit);

    // Authenticate.
    client.Authenticate("userName", "password");

    // Do something here...
    client.DownloadFile("/my remote file.dat", "my local file");

    // Disconnect.
    client.Disconnect();
}

/// <summary>
/// Returns all issues of the given certificate.
/// </summary>
/// <param name="status">The certificate verification result.</param>
/// <param name="code">The error code.</param>
/// <returns>Certificate problems.</returns>
private static string GetCertProblem(CertificateVerificationStatus status, int code)
{
    switch (status)
    {
        case CertificateVerificationStatus.TimeNotValid:
            return "Server's certificate has expired or is not valid yet.";

        case CertificateVerificationStatus.Revoked:
            return "Server's certificate has been revoked.";

        case CertificateVerificationStatus.UnknownCa:
            return "Server's certificate was issued by an unknown authority.";

        case CertificateVerificationStatus.UntrustedRoot:
            return "Server's certificate was issued by an untrusted authority.";

        case CertificateVerificationStatus.IncompleteChain:
            return "Server's certificate does not chain up to a trusted root authority.";

        case CertificateVerificationStatus.Malformed:
            return "Server's certificate is malformed.";

        case CertificateVerificationStatus.CnNotMatch:
            return "Server hostname does not match the certificate.";

        case CertificateVerificationStatus.UnknownError:
            return string.Format("Error {0:x} encountered while validating server's certificate.", code);

        default:
            return status.ToString();
    }
}

static void client_CertificateReceived(object sender, ComponentPro.Security.CertificateReceivedEventArgs e)
{
    X509Certificate2 cert = e.ServerCertificates[0];

    CertificateVerificationStatus status = e.Status;

    CertificateVerificationStatus[] values = (CertificateVerificationStatus[])Enum.GetValues(typeof(CertificateVerificationStatus));

    StringBuilder sbIssues = new StringBuilder();
    for (int i = 0; i < values.Length; i++)
    {
        // Matches the validation status?
        if ((status & values[i]) == 0)
            continue;

        // The issue is processed.
        status ^= values[i];

        sbIssues.AppendFormat("{0}\r\n", GetCertProblem(values[i], e.ErrorCode));
    }

    Console.WriteLine("Issue: " + sbIssues.ToString());

    Console.WriteLine("Subject: " + cert.SubjectName.Name);
    Console.WriteLine("Issuer: " + cert.IssuerName.Name);
    Console.WriteLine("Effective Date: " + cert.NotBefore);
    Console.WriteLine("Expiry Date: " + cert.NotAfter);
    Console.ResetColor();
    Console.Write("Do you want to accept this certificate (Add to trusted list, Yes, No) [a,y,n]?");

    string response = Console.ReadLine().Trim().ToLower();

    // Add certiticate of the issuer CA to the trusted list.
    if (response == "a")
    {
        e.AddToTrustedRoot = true;
    }
    else if (response == "y")
    {
        e.Accept = true;
    }
}
Shared Sub Main()
    ' Create a new class instance.
    Dim client As New Ftp()

    AddHandler client.CertificateReceived, AddressOf client_CertificateReceived

    ' Connect to the FTP server.
    client.Connect("myserver", 21, SslSecurityMode.Explicit)

    ' Authenticate.
    client.Authenticate("userName", "password")

    ' Do something here...
    client.DownloadFile("/my remote file.dat", "my local file")

    ' Disconnect.
    client.Disconnect()
End Sub

''' <summary>
''' Returns all issues of the given certificate.
''' </summary>
''' <param name="status">The certificate verification result.</param>
''' <param name="code">The error code.</param>
''' <returns>Certificate problems.</returns>
Private Shared Function GetCertProblem(ByVal status As CertificateVerificationStatus, ByVal code As Integer) As String
    Select Case status
        Case CertificateVerificationStatus.TimeNotValid
            Return "Server's certificate has expired or is not valid yet."

        Case CertificateVerificationStatus.Revoked
            Return "Server's certificate has been revoked."

        Case CertificateVerificationStatus.UnknownCa
            Return "Server's certificate was issued by an unknown authority."

        Case CertificateVerificationStatus.UntrustedRoot
            Return "Server's certificate was issued by an untrusted authority."

        Case CertificateVerificationStatus.IncompleteChain
            Return "Server's certificate does not chain up to a trusted root authority."

        Case CertificateVerificationStatus.Malformed
            Return "Server's certificate is malformed."

        Case CertificateVerificationStatus.CnNotMatch
            Return "Server hostname does not match the certificate."

        Case CertificateVerificationStatus.UnknownError
            Return String.Format("Error {0:x} encountered while validating server's certificate.", code)

        Case Else
            Return status.ToString()
    End Select
End Function

Private Shared Sub client_CertificateReceived(ByVal sender As Object, ByVal e As ComponentPro.Security.CertificateReceivedEventArgs)
    Dim cert As X509Certificate2 = e.ServerCertificates(0)

    Dim status As CertificateVerificationStatus = e.Status

    Dim values() As CertificateVerificationStatus = CType(System.Enum.GetValues(GetType(CertificateVerificationStatus)), CertificateVerificationStatus())

    Dim sbIssues As New StringBuilder()
    For i As Integer = 0 To values.Length - 1
        ' Matches the validation status?
        If (status And values(i)) = 0 Then
            Continue For
        End If

        ' The issue is processed.
        status = status Xor values(i)

        sbIssues.AppendFormat("{0}" & vbCrLf, GetCertProblem(values(i), e.ErrorCode))
    Next i

    Console.WriteLine("Issue: " & sbIssues.ToString())

    Console.WriteLine("Subject: " & cert.SubjectName.Name)
    Console.WriteLine("Issuer: " & cert.IssuerName.Name)
    Console.WriteLine("Effective Date: " & cert.NotBefore)
    Console.WriteLine("Expiry Date: " & cert.NotAfter)
    Console.ResetColor()
    Console.Write("Do you want to accept this certificate (Add to trusted list, Yes, No) [a,y,n]?")

    Dim response As String = Console.ReadLine().Trim().ToLower()

    ' Add certiticate of the issuer CA to the trusted list.
    If response = "a" Then
        e.AddToTrustedRoot = True
    ElseIf response = "y" Then
        e.Accept = True
    End If
End Sub

CertificateReceived event

The CertificateReceived event is triggered when Ultimate FTP has received the server's certificate. For more details, visit topic Verifying server's certificate.

ListItemReceived event

ListItemReceived event is triggered when a file and directory listing item has been received by ListDirectory, ListRawName or ListName methods. By handling this event, you can display information of the received FTP item or even parse the raw data of the received item line.

The following steps guide you on how to handle this event.

static void Main()
{
    // Create a new class instance.
    Ftp client = new Ftp();

    client.ListItemReceived += client_ListItemReceived;

    // Connect to the FTP server.
    client.Connect("demo.componentpro.com");            

    // Or you can specify the FTP port with
    // client.Connect("myserver", 21);

    // Authenticate.
    client.Authenticate("test", "test");
    
    // ...

    // Get file list in the currently working directory.
    client.ListDirectory();
    
    // ...

    // Disconnect.
    client.Disconnect();
}

static void client_ListItemReceived(object sender, FtpListItemReceivedEventArgs e)
{
    Console.WriteLine("Received raw line: " + e.RawLine);
    Console.WriteLine("FTP file: " + e.File.ToString());

    // Ignore files with name containing "tmp" phrase.
    if (e.File.Name.IndexOf("tmp") != -1) 
        e.Ignore();
}
Shared Sub Main()
    ' Create a new class instance.
    Dim client As New Ftp()

    AddHandler client.ListItemReceived, AddressOf client_ListItemReceived

    ' Connect to the FTP server.
    client.Connect("demo.componentpro.com")

    ' Or you can specify the FTP port with
    ' client.Connect("myserver", 21);

    ' Authenticate.
    client.Authenticate("test", "test")

    ' ...

    ' Get file list in the currently working directory.
    client.ListDirectory()

    ' ...

    ' Disconnect.
    client.Disconnect()
End Sub

Private Shared Sub client_ListItemReceived(ByVal sender As Object, ByVal e As FtpListItemReceivedEventArgs)
    Console.WriteLine("Received raw line: " & e.RawLine)
    Console.WriteLine("FTP file: " & e.File.ToString())

    ' Ignore files with name containing "tmp" phrase.
    If e.File.Name.IndexOf("tmp") <> -1 Then
        e.Ignore()
    End If
End Sub
static void Main()
{
    // Create a new Ftp instance.
    Ftp client = new Ftp();

    // Connect to the FTP server.
    client.Connect("demo.componentpro.com");

    // Authenticate.
    client.Authenticate("test", "test");

    // Register an event handler.
    client.Progress += client_Progress;

    // Upload file "c:\test.zip".
    client.UploadFile("c:\\test.zip", "test.zip");

    // And download file "test.zip".
    client.DownloadFile("test.zip", "test_download.zip");

    // Disconnect.
    client.Disconnect();
}

static void client_Progress(object sender, FileSystemProgressEventArgs e)
{
    if (e.State == TransferState.Uploading)
        Console.Write("\rUploaded: {0} bytes ({1}% completed) - {2}", e.BytesTransferred, e.Percentage, e.DestinationPath);
    else if (e.State == TransferState.Downloading)
        Console.Write("\rDownloaded: {0} bytes ({1}% completed) - {2}", e.BytesTransferred, e.Percentage, e.SourcePath);
}
Shared Sub Main()
    ' Create a new Ftp instance.
    Dim client As New Ftp()

    ' Connect to the FTP server.
    client.Connect("demo.componentpro.com")

    ' Authenticate.
    client.Authenticate("test", "test")

    ' Register an event handler.
    AddHandler client.Progress, AddressOf client_Progress

    ' Upload file "c:\test.zip".
    client.UploadFile("c:\test.zip", "test.zip")

    ' And download file "test.zip".
    client.DownloadFile("test.zip", "test_download.zip")

    ' Disconnect.
    client.Disconnect()
End Sub

Private Shared Sub client_Progress(ByVal sender As Object, ByVal e As FileSystemProgressEventArgs)
    If e.State = TransferState.Uploading Then
        Console.Write(vbCr & "Uploaded: {0} bytes ({1}% completed) - {2}", e.BytesTransferred, e.Percentage, e.DestinationPath)
    ElseIf e.State = TransferState.Downloading Then
        Console.Write(vbCr & "Downloaded: {0} bytes ({1}% completed) - {2}", e.BytesTransferred, e.Percentage, e.SourcePath)
    End If
End Sub

Progress event

Progress event is triggered when a block of data has been sent or received. By handling this event, you can display transfer progress information, source file name, destination file name, etc.

TransferConfirm event

When transferring lots of files using the Upload or Download methods, things can occasionally go wrong due to unpredictable problems. Those issues may be:

  • A target file already exists
  • Recursive link detected
  • Directory listing failure
  • File transfer failure
  • ...

To be informed about such errors, handle the TransferConfirm event. In the handler of that event, you can choose how to react to the issue by setting the TransferConfirmEventArgs.NextAction property. The TransferConfirmEventArgs data object of the TransferConfirm event has lots of useful members to help you know what the issue is, what the source and destination files are and what the reaction should be.

The following code snippet demonstrates how to handle the TransferConfirm event to append "(1)" phrase to the file name of an existing target file.

public static void Main()
{
    // Create a new instance of the Ftp class.
    using (Ftp client = new Ftp())
    {
        // Connect to the server.
        client.Connect(serverName, serverPort);

        // Authenticate the user
        client.Authenticate(userName, password);

        client.TransferConfirm += ClientOnTransferConfirm;

        // Download all files from "/data" to "d:\temp".
        client.Download("/data", @"d:\temp", true, FileOverwriteMode.Confirm);
    }
}

private static void ClientOnTransferConfirm(object sender, TransferConfirmEventArgs e)
{
    if (e.ConfirmReason == TransferConfirmReason.FileAlreadyExists)
    {
        string oldName = e.DestinationFileInfo.Name;
        int n = oldName.LastIndexOf('.');
        string ext = n != -1 ? oldName.Substring(n) : null;
        string name = n != -1 ? oldName.Substring(0, n) : oldName;
        e.NewName = name + "(1)" + ext;
        e.NextAction = TransferConfirmNextActions.Rename;
    }
}
Public Shared Sub Main()
    ' Create a new instance of the Ftp class.
    Using client As New Ftp()
        ' Connect to the server.
        client.Connect(serverName, serverPort)

        ' Authenticate the user
        client.Authenticate(userName, password)

        AddHandler client.TransferConfirm, AddressOf ClientOnTransferConfirm

        ' Download all files from "/data" to "d:\temp".
        client.Download("/data", "d:\temp", True, FileOverwriteMode.Confirm)
    End Using
End Sub

Private Shared Sub ClientOnTransferConfirm(ByVal sender As Object, ByVal e As TransferConfirmEventArgs)
    If e.ConfirmReason = TransferConfirmReason.FileAlreadyExists Then
        Dim oldName As String = e.DestinationFileInfo.Name
        Dim n As Integer = oldName.LastIndexOf("."c)
        Dim ext As String
        If n <> -1 Then
            ext = oldName.Substring(n)
        Else
            ext = Nothing
        End If
        Dim name As String
        If n <> -1 Then
            name = oldName.Substring(0, n)
        Else
            name = oldName
        End If
        e.NewName = name & "(1)" & ext
        e.NextAction = TransferConfirmNextActions.Rename
    End If
End Sub
static void Main()
{
    // Create a new class instance.
    Ftp client = new Ftp();

    // Register event handlers.
    client.CommandResponse += client_CommandResponse;

    // Connect to the FTP server.
    client.Connect("demo.componentpro.com");

    // Authenticate.
    client.Authenticate("test", "test");

    // ...

    // Do something here
    client.UploadFile("c:\\test.dat", "/test.dat");

    // ...

    // Disconnect.
    client.Disconnect();
}

static void client_CommandResponse(object sender, CommandResponseEventArgs e)
{
    if (e.Command != null)
        Console.WriteLine("CMD>       " + e.Command);
    else
        Console.WriteLine("RESPONSE>  " + e.Response);
}
Shared Sub Main()
    ' Create a new class instance.
    Dim client As New Ftp()

    ' Register event handlers.
    AddHandler client.CommandResponse, AddressOf client_CommandResponse

    ' Connect to the FTP server.
    client.Connect("demo.componentpro.com")

    ' Authenticate.
    client.Authenticate("test", "test")

    ' ...

    ' Do something here
    client.UploadFile("c:\test.dat", "/test.dat")

    ' ...

    ' Disconnect.
    client.Disconnect()
End Sub

Private Shared Sub client_CommandResponse(ByVal sender As Object, ByVal e As CommandResponseEventArgs)
    If e.Command IsNot Nothing Then
        Console.WriteLine("CMD>       " & e.Command)
    Else
        Console.WriteLine("RESPONSE>  " & e.Response)
    End If
End Sub

CommandResponse event

The CommandResponse event is triggered when a command has been sent to the FTP server or when Ultimate FTP component has received a response from the server. This event is commonly used to add trace log capabilities to your applications. For more details on how to handle this event, visit Making a trace log using events. There is still another convenient way to add log capabilities to your application is using the XTrace class.

StateChanged event

The StateChanged event is triggered when the state of the Ftp object has been changed. By handling this event, you will get notification when a connection has been established or the connection has been lost.

The following steps guide you on how to handle this event.

static void Main()
{
    // Create a new class instance.
    Ftp client = new Ftp();

    client.StateChanged += client_StateChanged;

    // Connect to the FTP server.
    client.Connect("localhost");

    // Authenticate.
    client.Authenticate("test", "test");

    // ...

    // Do something here

    // ...

    // Disconnect.
    client.Disconnect();
}

static void client_StateChanged(object sender, RemoteFileSystemStateChangedEventArgs e)
{
    Console.WriteLine("State changed, old state: {0}, new state: {1}", e.OldState, e.State);
}
Shared Sub Main()
    ' Create a new class instance.
    Dim client As New Ftp()

    AddHandler client.StateChanged, AddressOf client_StateChanged

    ' Connect to the FTP server.
    client.Connect("localhost")

    ' Authenticate.
    client.Authenticate("test", "test")

    ' ...

    ' Do something here

    ' ...

    ' Disconnect.
    client.Disconnect()
End Sub

Private Shared Sub client_StateChanged(ByVal sender As Object, ByVal e As RemoteFileSystemStateChangedEventArgs)
    Console.WriteLine("State changed, old state: {0}, new state: {1}", e.OldState, e.State)
End Sub

Advanced FTP features

The library also comes with some advanced features below:

Unified API for SFTP and FTP

FTP and SFTP are two different file transfer protocols, but they both cover same task - transferring files over the network. Our Unified File System library lets you write the same code for file management with FTP, SFTP, and ZIP. One of the benefits of having similar API across Sftp, Ftp, and Zip classes is that the time required to familiarize yourself with a new protocol is minimized or eliminated altogether. The interface IRemoteFileSystem that both Ftp and Sftp classes implement, defines most Sftp and Ftp methods, properties, and events, making it easy to write the single code segment to work with both protocols as shown in the example below:

// The IRemoteFileSystem interface is used for all remote file systems, including Ftp, Sftp, and Scp.
IRemoteFileSystem client;

// Create a new class instance.
if (isFtp)
    client = new Ftp();
else
    client = new Sftp();

// Connect to the server
client.Connect(serverName, serverPort);
// Authenticate the user.
client.Authenticate(userName, password);

// Upload files in "C:\data" to "/data".
client.Upload(@"C:\data", "/data");

// Download a remote file.
client.DownloadFile("/content/file.txt", @"c:\data\file.txt");

// Close the connection.
client.Disconnect();
' The IRemoteFileSystem interface is used for all remote file systems, including Ftp, Sftp, and Scp.
Dim client As IRemoteFileSystem

' Create a new class instance.
If isFtp Then
    client = New Ftp()
Else
    client = New Sftp()
End If

' Connect to the server
client.Connect(serverName, serverPort)
' Authenticate the user.
client.Authenticate(userName, password)

' Upload files in "C:\data" to "/data".
client.Upload("C:\data", "/data")

' Download a remote file.
client.DownloadFile("/content/file.txt", "c:\data\file.txt")

' Close the connection.
client.Disconnect()
// Create a new instance of the Ftp class.
using (Ftp client = new Ftp())
{
    // Connect to the server.
    client.Connect(serverName);

    // Authenticate the user
    client.Authenticate(userName, password);

    // Initialize a queue with 5 threads.
    TransferQueue queue = new TransferQueue(5);
    // Add items to the queue
    queue.Add(DiskFileSystem.Default.CreateFileInfo(@"C:\data\folder1"), client.CreateFileInfo("/data/folder1"), false, null, 0);
    queue.Add(DiskFileSystem.Default.CreateFileInfo(@"C:\data\folder2"), client.CreateFileInfo("/data/folder2"), false, null, 0);
    queue.Add(DiskFileSystem.Default.CreateFileInfo(@"C:\data\file1"), client.CreateFileInfo("/data/file1"), false, null, 0);

    // Start the queue.
    // It immediately returns control to the caller's process.
    queue.Start(false);

    // ...
    // Here we can add more items to the queue while it's in progress
    queue.Add(DiskFileSystem.Default.CreateFileInfo(@"C:\data\folder3"), client.CreateFileInfo("/data/folder3"), false, null, 0);

    // ...

    // or we can change the number of threads.
    // e.g. use 5 more threads -> 10 threads.
    queue.Threads = 10;

    // ...

    // the queue can be paused.
    queue.Stop();

    // ...
    // and then resumed
    queue.Start(true);

    // ...
    // we can also wait until it completes.
    queue.Wait(true);
}
' Create a new instance of the Ftp class.
Using client As New Ftp()
    ' Connect to the server.
    client.Connect(serverName)

    ' Authenticate the user
    client.Authenticate(userName, password)

    ' Initialize a queue with 5 threads.
    Dim queue As New TransferQueue(5)
    ' Add items to the queue
    queue.Add(DiskFileSystem.Default.CreateFileInfo("C:\data\folder1"), client.CreateFileInfo("/data/folder1"), False, Nothing, 0)
    queue.Add(DiskFileSystem.Default.CreateFileInfo("C:\data\folder2"), client.CreateFileInfo("/data/folder2"), False, Nothing, 0)
    queue.Add(DiskFileSystem.Default.CreateFileInfo("C:\data\file1"), client.CreateFileInfo("/data/file1"), False, Nothing, 0)

    ' Start the queue.
    ' It immediately returns control to the caller's process.
    queue.Start(False)

    ' ...
    ' Here we can add more items to the queue while it's in progress
    queue.Add(DiskFileSystem.Default.CreateFileInfo("C:\data\folder3"), client.CreateFileInfo("/data/folder3"), False, Nothing, 0)

    ' ...

    ' or we can change the number of threads.
    ' e.g. use 5 more threads -> 10 threads.
    queue.Threads = 10

    ' ...

    ' the queue can be paused.
    queue.Stop()

    ' ...
    ' and then resumed
    queue.Start(True)

    ' ...
    ' we can also wait until it completes.
    queue.Wait(True)
End Using

Transfer queue

Are you looking for a component that has the capability to add files and directories to a queue and start, stop or pause the queue any time? The TransferQueue class is designed to do that job. The free LionFTP client is an example of how a WinForms application makes use of that class.

That class also allows you to add files to transfer, sort file list, set item priority on-the-fly. It also lets you change the number of threads used to transfer files while the queue is still in process, start, pause and resume the queue.

Determine local PC and server time difference

To determine the time difference between the client and the SFTP server, call the GetServerTimeDifference method. We will take advantage of this method with the following example.

// Create a new class instance.
Ftp client = new Ftp();

// Connect to the FTP server.
client.Connect("myserver");

// Authenticate.
client.Authenticate("userName", "password");

// ...

// Get the time difference between the server and the client.
TimeSpan ts = client.GetServerTimeDifference();

Console.WriteLine("Time difference: " + ts.ToString());

// ...

// Disconnect.
client.Disconnect();
' Create a new class instance.
Dim client As New Ftp()

' Connect to the FTP server.
client.Connect("myserver")

' Authenticate.
client.Authenticate("userName", "password")

' ...

' Get the time difference between the server and the client.
Dim ts As TimeSpan = client.GetServerTimeDifference()

Console.WriteLine("Time difference: " & ts.ToString())

' ...

' Disconnect.
client.Disconnect()
// Create a new class instance.
Ftp client = new Ftp();

// Connect to the FTP server.
client.Connect("localhost");

// Authenticate.
client.Authenticate("test", "test");

// ...

// Download remote file '/test.dat' to 'c:\test.dat'
long transferred = await client.DownloadFileAsync("/test.dat", "c:\\test.dat");

// ...

Console.WriteLine("Bytes transferred: " + transferred);

// Disconnect.
client.Disconnect();
' Create a new class instance.
Dim client As New Ftp()

' Connect to the FTP server.
client.Connect("localhost")

' Authenticate.
client.Authenticate("test", "test")

' ...

' Download remote file '/test.dat' to 'c:\test.dat'
Dim transferred As Long = Await client.DownloadFileAsync("/test.dat", "c:\test.dat")

' ...

Console.WriteLine("Bytes transferred: " & transferred)

' Disconnect.
client.Disconnect()

Use asynchronous methods

Ftp provides a number of methods allowing you to asynchronously connect, login, upload, download, etc. Their names always end with Async. This means the method will begin some operation on a new thread and immediately return to the caller. When the operation has completed, the corresponding event will be raised notifying you that the operation has completed and in the event handler method you can check for the error and use the result, if provided.

The example following demonstrates how to connect to an FTP server and download a file asynchronously:

Other FTP features

The component also offers a number of useful features listed below:

SITE command

Use the Site method to execute a server-specific command on the FTP server.

// Create a new class instance.
Ftp client = new Ftp();

// Connect to the FTP server.
client.Connect("myserver");

// Authenticate.
client.Authenticate("userName", "password");

// ...

// Execute SITE HELP command on the server and return a response.
// SITE HELP usually returns a list of SITE commands supported by the FTP server.
string response = client.Site("HELP");

Console.WriteLine("Response: " + response);

// Change access rights to a file on a unix-like FTP server.
client.Site("CHMOD 777 file1.txt");

// Get current user's group membership.
response = client.Site("GROUPS");
Console.WriteLine(response);

// ...

// Disconnect.
client.Disconnect();
' Create a new class instance.
Dim client As New Ftp()

' Connect to the FTP server.
client.Connect("myserver")

' Authenticate.
client.Authenticate("userName", "password")

' ...

' Execute SITE HELP command on the server and return a response.
' SITE HELP usually returns a list of SITE commands supported by the FTP server.
Dim response As String = client.Site("HELP")

Console.WriteLine("Response: " & response)

' Change access rights to a file on a unix-like FTP server.
client.Site("CHMOD 777 file1.txt")

' Get current user's group membership.
response = client.Site("GROUPS")
Console.WriteLine(response)

' ...

' Disconnect.
client.Disconnect()
// Create a new class instance.
Ftp ftp1 = new Ftp();

// Connect to the FTP server.
ftp1.Connect("myserver");

// Authenticate.
ftp1.Authenticate("userName", "password");

// ...

// Create a new class instance.
Ftp ftp2 = new Ftp();

// Connect to the FTP server.
ftp2.Connect("myserver2");

// Authenticate.
ftp2.Authenticate("userName", "password");

// ...

// Copy "/myfile.x" file from the first FTP server to the second one.
ftp1.RemoteCopy(ftp2, "/myfile.x", "/myfile.x");


// Disconnect.
ftp1.Disconnect();

ftp2.Disconnect();
' Create a new class instance.
Dim ftp1 As New Ftp()

' Connect to the FTP server.
ftp1.Connect("myserver")

' Authenticate.
ftp1.Authenticate("userName", "password")

' ...

' Create a new class instance.
Dim ftp2 As New Ftp()

' Connect to the FTP server.
ftp2.Connect("myserver2")

' Authenticate.
ftp2.Authenticate("userName", "password")

' ...

' Copy "/myfile.x" file from the first FTP server to the second one.
ftp1.RemoteCopy(ftp2, "/myfile.x", "/myfile.x")


' Disconnect.
ftp1.Disconnect()

ftp2.Disconnect()

Server-to-server transfers (FXP)

Some FTP servers support transfer files from one to another directly, without copying them to the client. To utilize that advanced feature, use the RemoteCopy method.

Send custom FTP commands

Explicitly sending commands to an FTP server is usually not necessary. Almost all commands that could conceivably be sent to an FTP server are encapsulated by high-level methods. However, to send a command to an FTP server, simply call the SendCommand method, and to get the response from the FTP server, call the ReadResponse method.

The example below sends the "FEAT" command to an FTP server and prints out the response:

// Create a new Ftp instance.
Ftp client = new Ftp();

// Connect to the FTP server.
client.Connect("server");

// Authenticate.
client.Authenticate("username", "password");

// Send command
client.SendCommand("FEAT");

// Print out the response
FtpResponse res = client.ReadResponse();
Console.WriteLine(res.RawResponse);

// Disconnect.
client.Disconnect();
' Create a new Ftp instance.
Dim client As New Ftp()

' Connect to the FTP server.
client.Connect("server")

' Authenticate.
client.Authenticate("username", "password")

' Send command
client.SendCommand("FEAT")

' Print out the response
Dim res As FtpResponse = client.ReadResponse()
Console.WriteLine(res.RawResponse)

' Disconnect.
client.Disconnect()
// Register FtpWebRequest for the specified schema.
WebRequest.RegisterPrefix("ftp://", ComponentPro.Net.FtpWebRequest.Creator);

Console.WriteLine("Sending request...");

// Create a WebRequest for the specified URL. 
WebRequest request = WebRequest.Create("ftp://ftp.example.net/pub/myfile.zip");

// Send the WebRequest and waits for a response.
WebResponse response = request.GetResponse();

// Get remote file stream for downloading.
Stream remoteFileStream = response.GetResponseStream();

Stream localFileStream = File.Create("myfile.zip");

// Create a new buffer to download.
byte[] buffer = new byte[1024];
int n;
do
{
    // Read data from the remote file stream.
    n = remoteFileStream.Read(buffer, 0, buffer.Length);
    // Write to the local file stream.
    localFileStream.Write(buffer, 0, n);
} while (n > 0);

Console.WriteLine("Response Received.");

localFileStream.Close();

// Release the resources of the response.
remoteFileStream.Close();
' Register FtpWebRequest for the specified schema.
WebRequest.RegisterPrefix("ftp://", ComponentPro.Net.FtpWebRequest.Creator)

Console.WriteLine("Sending request...")

' Create a WebRequest for the specified URL. 
Dim request As WebRequest = WebRequest.Create("ftp://ftp.example.net/pub/myfile.zip")

' Send the WebRequest and waits for a response.
Dim response As WebResponse = request.GetResponse()

' Get remote file stream for downloading.
Dim remoteFileStream As Stream = response.GetResponseStream()

Dim localFileStream As Stream = File.Create("myfile.zip")

' Create a new buffer to download.
Dim buffer(1023) As Byte
Dim n As Integer
Do
    ' Read data from the remote file stream.
    n = remoteFileStream.Read(buffer, 0, buffer.Length)
    ' Write to the local file stream.
    localFileStream.Write(buffer, 0, n)
Loop While n > 0

Console.WriteLine("Response Received.")

localFileStream.Close()

' Release the resources of the response.
remoteFileStream.Close()

Using FtpWebRequest

The following code example illustrates how to use the FtpWebRequest class to download a remote file from an FTP server.