What does the generic “Unable to transfer file…” FileSystemException mean?

The exception is raised when a file is unable to transfer. Some people get confused because they dont know what is going on. It’s our mistake not to append error details to the message. In fact, you can see the error details by accessing the InnerException property of the exception object. This give you an insight of the problem that you have encoutered.

In our new version of the Ultimate FTP component, we will include many enhancements, as well as more meaningful information added to some so-generic error messages.

Using FtpWebRequest

The following code example illustrates how to use the FtpWebRequest class to download a remote file from an FTP server.

C#:

// 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();

VB.NET:

' 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()

Sending custom commands to an FTP server

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:

C#:

// 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();

VB.NET

' Create a new FtpClient 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.Text)
' Disconnect.
client.Disconnect()

Directly downloading files to a ZIP file

All file system classes, including SFTP, FTP, and ZIP, base on the the unified FileSystem base class, making it easy to transfer files and directories directly from one system to another. By creating or opening a ZIP file and call the DownloadFiles method of the Ftp class, you can achieve the goal in an elegant way. Moreover, the code you have written for FTP system can also be used for the Sftp and Scp classes of the Ultimate SFTP component. The following code demonstrates how to achieve the goal with the Ftp class and the Ultimate ZIP component:

// Create a ZIP file.
Zip zipFile = new Zip();

zipFile.Create(@"c:\test.zip");

Ftp ftp = new Ftp();
// Connect to the FTP server.
ftp.Connect("demo.componentpro.com", 21);
// Authenticate.
ftp.Authenticate("test", "test");
// Create a new instance of the TransferOptions class.
// There are many advanced option in the TransferOptions class such as Recursive, allowing empty directory creation, etc.
TransferOptions opt = new TransferOptions();
// Download files(*.cs, *.vb, and *.exe files) from the root folder to the ZIP file directly.
ftp.DownloadFiles("/*.cs;*.vb;*.exe", (IFileInfo[])null, zipFile, "", opt);
ftp.Disconnect();

zipFile.Close();

VB.NET:

' Create a ZIP file.
Dim zipFile As New Zip()

zipFile.Create("c:\test.zip")

Dim ftp As New Ftp()
' Connect to the FTP server.
ftp.Connect("demo.componentpro.com", 21)
' Authenticate.
ftp.Authenticate("test", "test")
' Create a new instance of the TransferOptions class.
' There are many advanced option in the TransferOptions class such as Recursive, allowing empty directory creation, etc.
Dim opt As New TransferOptions()
' Download files(*.cs, *.vb, and *.exe files) from the root folder to the ZIP file directly.
ftp.DownloadFiles("/*.cs;*.vb;*.exe", CType(Nothing, IFileInfo()), zipFile, "", opt)
ftp.Disconnect()

zipFile.Close()

Click here to download the Ultimate FTP Component for .NET, or here to download the .NET CF version.

Multi-part Download with Multiple Threads

This topic shows you how to use multiple threads to connect to an FTP server and download a file. First, we need to define a class which contains information about the file, and the threads. In this example, it’s named GlobalInfo. And then we define a class for Ftp Threads, it’s named FtpThread. Finally, in the main routine, we create and start 3 threads to download the parts of the file. As a result, the download speed is improved if the file is large. We take advantage of the GetDownloadStream method with the following example code:

C#:

// Example Description : Shows how to use GetDownloadStream method to download multiple parts of a remote file using 3 threads.
using System;
using System.Collections.Generic;
using System.Text;
using System.IO;
using ComponentPro.Net;
using System.Threading;

namespace Samples
{
    // Main Code
    class GlobalInfo
    {
        // Maintain some information about the threads.
        public int CompletedThreads;
        public int Threads;
        public ManualResetEvent Event;
        public byte[][] Streams;
        public long Length = -1;
        public int BlockSize;
        public bool Finish;
    }

    class FtpThread
    {
        int _offset;
        int _blockSize;
        GlobalInfo _info;
        Ftp _client;
        int _index;
        
        public FtpThread(GlobalInfo info, int index)
        {
            _info = info;
            _index = index;
        }

        public void Start()
        {
            const string remoteFile = "/pub/test.zip";
            _client = new Ftp();
            _client.Connect("demo.componentpro.com");
            _client.Authenticate("test", "test");

            byte[] buf;

            lock (_info)
            {
                if (_info.Length == -1)
                {
                    // Get file length.
                    _info.Length = _client.GetFileLength(remoteFile);
                    // Calculate block size.
                    _info.BlockSize = (int)(_info.Length / _info.Threads);
                    _info.Streams = new byte[_info.Threads][];
                }

                // Calculate offset.
                _offset = _info.BlockSize * _index;
                _blockSize = (int)((_index == _info.Threads - 1) ? (_info.Length - _index * _info.BlockSize) : _info.BlockSize);

                buf = new byte[_blockSize];
                _info.Streams[_index] = buf;            
            }

            // Get download stream.
            Stream downloader = _client.GetDownloadStream(remoteFile, SeekOrigin.Begin, _offset);
            int count = 0;
            // Download data.
            while (true)
            {
                int size = (count + 4048 > _blockSize) ? (_blockSize - count) : 4048;
                int read = downloader.Read(buf, count, size);
                if (count + read >= _blockSize || read == 0)
                    break;
                count += read;
            } 
            downloader.Close();            

            _client.Disconnect();

            lock (_info)
            {
                _info.CompletedThreads++;
                if (_info.CompletedThreads == _info.Threads && !_info.Finish)
                {
                    _info.Event.Set();
                    // All threads have completed.

                    // Combine
                    using (FileStream sw = System.IO.File.OpenWrite(@"c:\temp\test.zip"))
                    {
                        foreach (byte[] s in _info.Streams)
                        {
                            sw.Write(s, 0, (int)s.Length);
                        }
                    }

                    _info.Finish = true;
                }
            }
        }
    }

    class MultiParts
    {
        static ManualResetEvent _event = new ManualResetEvent(false);
        static Ftp client;

        static void Main()
        {
            const int threads = 3;

            // Use 3 threads to download a remote file to streams and then save the streams into a local file.
            int offset = 0;
            
            GlobalInfo ginfo = new GlobalInfo();
            ginfo.Threads = threads;
            ginfo.Event = _event;

            for (int i = 0; i < threads; i++)
            {
                FtpThread fthread = new FtpThread(ginfo, i);
                Thread th = new Thread(fthread.Start);
                th.Start();
            }
            _event.WaitOne();
        }
    }
    // End Main Code
}

VB.NET:

' Example Description : Shows how to use GetDownloadStream method to download multiple parts of a remote file using 3 threads.

' Imports Microsoft.VisualBasic
Imports System
Imports System.Collections.Generic
Imports System.Text
Imports System.IO
Imports ComponentPro.Net
Imports System.Threading

Namespace Samples
	' Main Code
	Friend Class GlobalInfo
		' Maintain some information about the threads.
		Public CompletedThreads As Integer
		Public Threads As Integer
		Public [Event] As ManualResetEvent
		Public Streams()() As Byte
		Public Length As Long = -1
		Public BlockSize As Integer
		Public Finish As Boolean
	End Class

	Friend Class FtpThread
		Private _offset As Integer
		Private _blockSize As Integer
		Private _info As GlobalInfo
		Private _client As Ftp
		Private _index As Integer

		Public Sub New(ByVal info As GlobalInfo, ByVal index As Integer)
			_info = info
			_index = index
		End Sub

		Public Sub Start()
			Const remoteFile As String = "/pub/test.zip"
			_client = New Ftp()
            _client.Connect("demo.componentpro.com")
			_client.Authenticate("test", "test")

			Dim buf() As Byte

			SyncLock _info
				If _info.Length = -1 Then
					' Get file length.
					_info.Length = _client.GetFileLength(remoteFile)
					' Calculate block size.
					_info.BlockSize = CInt(Fix(_info.Length \ _info.Threads))
					_info.Streams = New Byte(_info.Threads - 1)(){}
				End If

				' Calculate offset.
				_offset = _info.BlockSize * _index
                If (_index = _info.Threads - 1) Then
                    _blockSize = CInt(Fix(_info.Length - _index * _info.BlockSize))
                Else
                    _blockSize = CInt(Fix(_info.BlockSize))
                End If

				buf = New Byte(_blockSize - 1){}
				_info.Streams(_index) = buf
			End SyncLock

			' Get download stream.
			Dim downloader As Stream = _client.GetDownloadStream(remoteFile, SeekOrigin.Begin, _offset)
			Dim count As Integer = 0
			' Download data.
			Do
				Dim size As Integer
				If (count + 4048 > _blockSize) Then
					size = _blockSize - count
				Else
					size = 4048
				End If
				Dim read As Integer = downloader.Read(buf, count, size)
				If count + read >= _blockSize OrElse read = 0 Then
					Exit Do
				End If
				count += read
			Loop
			downloader.Close()

			_client.Disconnect()

			SyncLock _info
				_info.CompletedThreads += 1
                If _info.CompletedThreads = _info.Threads AndAlso (Not _info.Finish) Then
                    _info.Event.Set()
                    ' All threads have completed.

                    ' Combine
                    Using sw As FileStream = System.IO.File.OpenWrite("c:\temp\test.zip")
                        For Each s As Byte() In _info.Streams
                            sw.Write(s, 0, CInt(Fix(s.Length)))
                        Next s
                    End Using

                    _info.Finish = True
                End If
			End SyncLock
		End Sub
	End Class

	Friend Class MultiParts
		Private Shared _event As New ManualResetEvent(False)
		Private Shared client As Ftp

		Shared Sub Main()
			Const threads As Integer = 3

			' Use 3 threads to download a remote file to streams and then save the streams into a local file.
			Dim offset As Integer = 0

			Dim ginfo As New GlobalInfo()
			ginfo.Threads = threads
			ginfo.Event = _event

			For i As Integer = 0 To threads - 1
				Dim fthread As New FtpThread(ginfo, i)
                Dim th As New Thread(AddressOf fthread.Start)
				th.Start()
			Next i
			_event.WaitOne()
		End Sub
	End Class
	' End Main Code
End Namespace

Click here to download the Ultimate FTP Component for .NET, or here to download the .NET CF version.

Ultimate FTP in Microsoft Windows PowerShell

ComponentPro would like to illustrate how to use Ultimate FTP in PowerShell in this topic. PowerShell is the new command line and scripting language developed by Microsoft to helps IT professionals complete their tasks more efficiently with greater control and productivity on Microsoft Windows Platforms. The PowerShell contains more than 130 command line tools especially designed for administrators.

Windows PowerShell is built on top of the .NET Framework, so it gives administrators a wide-range of methods and extensions. With Ultimate FTP, now you can upload and download files to FTP server easily with a few lines of code. Since PowerShell accepts and returns .NET objects, FTP classes are accessible to the PowerShell, in which you can use the component to build a complex application like a C# or VB.NET application. This component can be downloaded from our website.

To get start, we begin with uploading several files with a single line of code:

Unlike many other FTP components, Ultimate FTP enables you to upload and download multiple files with different extensions with a single line of code. We take advantages of this feature with the following PowerShell sample:

# Load DLL
Add-Type -Path C:\InstalledDir\ComponentPro.Ftp.dll
# Set source path and files to upload
$sourcePath = "C:\Temp\*.ps1;*.dat;*.zip"
# Set destination path
$destinationPath = "/my dir"
# Create a new instance of the Ftp class
$ftp = New-Object ComponentPro.Net.Ftp
$ftp.Connect("myserver")
$ftp.Authenticate("user", "pass")
# Upload files
$ftp.UploadFiles($sourcePath, $destinationPath)
$ftp.Close()
$ftp.Dispose()

Now we will download files from the FTP server to the local disk:

We gives you the ease-of-use of the FTP component not only in the upload methods, but also in the download methods. The following PowerShell code example demonstrates how to load the ComponentPro.Ftp.DLL assembly and download files from the FTP server:

# Load DLL
Add-Type -Path C:\InstalledDir\ComponentPro.Ftp.dll
# Set source path and files to upload
$sourcePath = "/my dir/*.ps1;*.dat;*.zip"
# Set destination path
$destinationPath = "C:\Temp2"
# Create a new instance of the Ftp class
$ftp = New-Object ComponentPro.Net.Ftp
$ftp.Connect("myserver")
$ftp.Authenticate("user", "pass")
# Download files
$ftp.DownloadFiles($sourcePath, $destinationPath)
$ftp.Close()
$ftp.Dispose()

How about FTP/SSL?

Basically to connect to an FTP/SSL server you only have to specify the SecurityMode as the third parameter of the Connect method as shown below:

C#:

ftp.Connect("myserver", 991, SecurityMode.Explicit);

VB.NET:

ftp.Connect("myserver", 991, SecurityMode.Explicit)

However PowerShell does not understand enums defined in our .NET assemblies. We must use an “Integer” as the third parameter of the Connect method with SecurityMode.None = 0, SecurityMode.Implicit = 1, SecurityMode.Explicit = 2, and SecurityMode.TumbleweedTunnel = 3.

$ftp.Connect("myserver", 991, 2)

Now you see with Ultimate FTP Component and a little knowledge of PowerShell language, you can build a comprehensive file transfer application running on the Windows PowerShell.

Click here to download the Ultimate FTP Component for .NET, or here to download the .NET CF version.

Listing a directory Asynchronously

In UltimateFtp, you can use BeginListDirectory, BeginListName or BeginListRawName methods of the Ftp class to asynchronously retrieve the list of files and directories in the specified directory on the FTP server. These methods retrieve the list asynchronously with execution occurring on a new thread, therefore it allows your next line of code to execute  immediately. The event ListDirectoryCompleted, ListNameCompleted or ListRawNameCompleted of the Ftp class under namespace ComponentPro.Net is raised when the BeginListDirectory, BeginListName or BeginListRawName is complete. In the handler method of the ListDirectoryCompleted, ListNameCompleted or ListRawNameCompleted event, you need to call the EndListDirectory, EndListName or EndListRawName method to finish the asynchronous operation.

The following image shows how the FTP Client Demo sample project shows contents of an FTP directory:

FTP Client Demo

To retrieve the list of files and directories in a directory on the FTP server asynchronously, you can simply perform the following steps

  1. Add the FTP component to your application. See Creating a WinForms Application or Creating a Web Application for more details.
  2. Add using directives to your code to create aliases for existing namespaces and avoid having to type the fully qualified type names.
  3. Create a new instance of the Ftp class.
  4. Now you can connect to the FTP server with Connect or BeginConnect methods. The code looks similar to the following:
    C#:

    // Create a new 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);

    VB.NET

    ' Create a new 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);
  5. Now you can call the BeginListDirectory to asynchronously retrieve the list of files and directories in the specified directory on the FTP server. Prior to calling BeginListDirectory method, you have to register an event handler to the ListDirectoryCompleted event (you do not need to do that before each call to the BeginListDirectory method, just before the first call). Upon completion of the operation, Ultimate FTP will raise the ListDirectoryCompleted event. When the event is raised, access information contained in the AsyncMethodCompletedEventArgs object. The code looks similar to the following:C#:
    // Register an event handler.
    client.ListDirectoryCompleted += client_ListDirectoryCompleted;
    // Get information of all files and directories in '/' remote dir.
    client.BeginListDirectory("/");

    VB.NET:

    ' Register an event handler.
    AddHandler client.ListDirectoryCompleted, AddressOf client_ListDirectoryCompleted
    ' Get information of all files and directories in '/' remote dir.
    client.BeginListDirectory("/")
  6. Now you need to write the code for client_ListDirectoryCompleted event handler. And in the client_ListDirectoryCompleted event handler, write your own code to do something like displaying the received list… The code looks similar to the following:
    C#:

    void client_ListDirectoryCompleted(object sender, AsyncMethodCompletedEventArgs e)
    {
       Ftp client = (Ftp)sender;
       try
       {
           // Get information of all files and directories in '/' remote dir.
           foreach (FtpFileInfo info in client.EndListDirectory(e.AsyncResult))
           {
               Console.WriteLine("Name: {0}, UserId: {1}, Permissions: {2}", info.Name, info.UserId, info.Permissions);
           }
       }
       catch (Exception exc)
       {
           Console.WriteLine("Error: " + exc.ToString());
       }
    }

    VB.NET

    Private Sub client_ListDirectoryCompleted(ByVal sender As Object, ByVal e As AsyncMethodCompletedEventArgs)
        Dim client As Ftp = CType(sender, Ftp)
        Try
            ' Get information of all files and directories in '/' remote dir.
            For Each info As FtpFileInfo In client.EndListDirectory(e.AsyncResult)
                Console.WriteLine("Name: {0}, UserId: {1}, Permissions: {2}", info.Name, info.UserId, info.Permissions)
            Next info
        Catch exc As Exception
            Console.WriteLine("Error: " & exc.ToString())
        End Try
    End Sub
  7. After completing your work, call the Disconnect method to close the FTP session.

Final Example Code using Ultimate FTP

C#:

public void DoAsyncListDirectory()
{
   // Create a new instance.
   Ftp client = new Ftp();
   // Connect to the FTP server.
   client.Connect("myserver");
   // Authenticate.
   client.Authenticate("test", "test");
   // ...
   // Register an event handler.
   client.ListDirectoryCompleted += client_ListDirectoryCompleted;
   // Get information of all files and directories in '/' remote dir.
   client.BeginListDirectory("/");
   // ...
   // Disconnect.
   client.Disconnect();
}
void client_ListDirectoryCompleted(object sender, AsyncMethodCompletedEventArgs e)
{
   Ftp client = (Ftp)sender;
   try
   {
       // Get information of all files and directories in '/' remote dir.
       foreach (FtpFileInfo info in client.EndListDirectory(e.AsyncResult))
       {
           Console.WriteLine("Name: {0}, UserId: {1}, Permissions: {2}", info.Name, info.UserId, info.Permissions);
       }
   }
   catch (Exception exc)
   {
       Console.WriteLine("Error: " + exc.ToString());
   }
}

VB.NET:

Public Sub DoAsyncListDirectory()
    ' Create a new instance.
    Dim client As New Ftp()
    ' Connect to the FTP server.
    client.Connect("myserver")
    ' Authenticate.
    client.Authenticate("test", "test")
    ' ...
    ' Register an event handler.
    AddHandler client.ListDirectoryCompleted, AddressOf client_ListDirectoryCompleted
    ' Get information of all files and directories in '/' remote dir.
    client.BeginListDirectory("/")
    ' ...
    ' Disconnect.
    client.Disconnect()
End Sub
Private Sub client_ListDirectoryCompleted(ByVal sender As Object, ByVal e As AsyncMethodCompletedEventArgs)
    Dim client As Ftp = CType(sender, Ftp)
    Try
        ' Get information of all files and directories in '/' remote dir.
        For Each info As FtpFileInfo In client.EndListDirectory(e.AsyncResult)
            Console.WriteLine("Name: {0}, UserId: {1}, Permissions: {2}", info.Name, info.UserId, info.Permissions)
        Next info
    Catch exc As Exception
        Console.WriteLine("Error: " & exc.ToString())
    End Try
End Sub

After listing a directory successfully, you can either use the asynchronous methods or synchronous methods to transfer files. For more details on transferring files, see this Transferring multiple files using Ultimate FTP topic.

Click here to download the Ultimate FTP Component for .NET, or here to download the .NET CF version.

ListItemReceived Event of the Ftp Class

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.

Handling Listing event

  1. Add using directives to your code to create aliases for existing namespaces and avoid having to type the fully qualified type names. The code looks similar to the following:
    C#  
    using ComponentPro.Net; 
    VB.NET  
    Imports ComponentPro.Net
  2. Create a new instance of the Ftp class.
  3. Register an event handler to the ListItemReceived event.
  4. Now you can connect to the FTP server with Connect methods. The code looks similar to the following:
    C#
    // Create a new instance.
    Ftp client = new Ftp();
    // Register an event handler.
    client.Listing += client_Listing;
    // Connect to the FTP server.
    client.Connect(“localhost”);
    VB.NET
    ‘ Create a new instance.
    Dim client As New Ftp()
    ‘ Register an event handler.
    AddHandler client.Listing, AddressOf client_Listing
    ‘ Connect to the FTP server.
    client.Connect(“localhost”)
  5. Use your user name and password to login with Authenticate methods. The code looks similar to the following:
    C#
    // Authenticate.
    client.Authenticate(“userName”, “password”);
    VB.NET
    ‘ Authenticate.
    client.Authenticate(“userName”, “password”)
  6. Do your tasks such as browsing a directory, upload, download files…
  7. After completing your work, call the Disconnect method to close the FTP session.

Final example code

C#
public void HandleListingEvent()
{
// Create a new instance.
Ftp client = new Ftp();
client.Listing += client_Listing;
// Connect to the FTP server.
client.Connect(“localhost”);
// Or you can specify the FTP port with
// client.Connect(“myserver”, 21);
// Authenticate.
client.Authenticate(“test”, “test”);
// …
// Get file list.
client.ListDirectory(“”);
// …
// Disconnect.
client.Disconnect();
}
void client_Listing(object sender, FtpListingEventArgs e)
{
Console.WriteLine(
“Received raw line: “ + e.RawData);
Console.WriteLine(
“FTP file: “ + e.File.ToString());
}
VB.NET
Public Sub HandleListingEvent()
‘ Create a new instance.
Dim client As New Ftp()
AddHandler client.Listing, AddressOf client_Listing
‘ Connect to the FTP server.
client.Connect(localhost)
‘ Or you can specify the FTP port with
‘ client.Connect(“myserver”, 21);
‘ Authenticate.
client.Authenticate(“test”, “test”)
‘ …
‘ Get file list.
client.ListDirectory(“”)
‘ …
‘ Disconnect.
client.Disconnect()
End Sub
Private Sub client_Listing(ByVal sender As Object, ByVal e As FtpListingEventArgs)
Console.WriteLine(“Received raw line: “ & e.RawData)
Console.WriteLine(“FTP file: “ & e.File.ToString())
End Sub

Click here to download the Ultimate FTP Component for .NET, or here to download the .NET CF version.

Security Overview and How to Connect to FTP/SSL Servers

This topic gives you an overview of Certificate and Security Modes for FTP/SSL. It also illustrates how to connect to FTP/SSL servers using Ultimate FTP.

What is a digital certificate?

Authentication is important for secure communications. Users must be able to prove their identity to the entities they are communicating with. In addition, they must be able to verify the identity of the entity communicating with them. This is accomplished by presenting or verifying some form of trusted credentials.

A digital certificate is a common credential that provides authentication. A trusted organization, called a Certificate Authority (CA), assigns a certificate to a user or entity and the user or entity then uses the certificate to prove itself to the other side. You may configure your system to accept any number of Certificate Authorities but ATP does not recommend this configuration. Completing the following steps to access the Certificates dialog box:

  1. In the Control Panel, double-click Internet Options.
  2. Select the Content tab, and then click Certificates.

Where do I get a certificate?

Certificates must come from a trusted CA. A user submits a certificate request to a CA and the CA returns a certificate for the user to use. Certificate used on our FTP server is generated by FileZila and CuteFTP. Listed below are some Certificate Authorities:

  • Microsoft Certificate Server – used for internal corporate Certificate delegation
  • VeriSign – (www.verisign.com) provides certificates for Internet users and servers

You always need a digital certificate installed to operate as a server. You only need a digital certificate installed on a client if the server requests authentication.

How does the authentication process work?

  1. The client normally initiates the TCP connection. The Connect method makes this TCP connection, sends a “client hello” message, and automatically responds to authentication requests received from the server.
  2. The server accepts the connection initiated by the client, constructs its digital credentials from the digital certificate referred to by the Server.Certificate Property, and sends its credentials to the client.
  3. Optionally, the server may also send an authentication request to the client.
  4. The client receives the server’s credentials, verifies it against the CAs it is configured to trust, and responds with its own credentials if an authentication request is received.
  5. If the client and server cannot negotiate a mutually acceptable security protocol, an error is generated and the connection is closed.
  6. If the client cannot validate the server’s credentials, an error is generated and the client closes the connection.
  7. If the server cannot validate the client’s credentials (if requested), an error is generated and the server closes the connection.
  8. Once protocol negotiation and authentication is successful, secure encryption/decryption is performed on all data passing over the connection.
  9. The session is terminated when one side closes the connection.

What is a certificate store?

A certificate store is a location on the system (memory, disk, registry, etc.) where certificates are stored for use. There are three major system stores and other minor stores. The three major stores are:

  • MY – personal certificates go here. (e.g. ATP code signing)
  • ROOT – certificates for Trusted Root Certificate Authorities.
  • CA – all other certificates.

What are the system store and the machine store?

The system store is the certificate store located in the HKEY_CURRENT_USER registry key. The machine store is the certificate store located in the HKEY_LOCAL_MACHINE registry key. Applications installed as a service should store their certificates in the machine store since there is no current user when running as a service.

What is the X500 naming convention?

This is a format for creating a distinguished name. The different parts of the name are described below:

  • C – country you are in (ex. US).
  • S – state you are in (ex. California).
  • L – locality value or city (ex. Walnut).
  • O – your organization (ex. ATP, Inc.).
  • OU – organizational unit (ex. Software Development).
  • CN – common name; typically the name of the system or user (Ex. www.mydomain.com).

Here are some examples of X500 names:

  • C=US, S=New York, L=Syracuse, O=ATP, Inc., OU=ATP, CN=My Machine
  • C=US, S=Georgia, L=Atlanta, O=MyOrg, OU=Toy Department, CN=John Doe

Explicit connection

When the client connects to the server using SSL, an SSL negotiation is initialized, the connection is secured and all following communication is being protected.

The code snippet below shows how to connect to an FTP server securely using Explicit security mode.

C#  
// Create a new instance.
Ftp client = new Ftp();
// Connect to the FTP server.
client.Connect(“myserver”, 21, SecurityMode.Explicit);
// Authenticate.
client.Authenticate(“userName”, “password”);
// Do something here…
client.DownloadFile(“/my remote file.dat”, “my local file”);
// Disconnect.
client.Disconnect();
VB.NET  
‘ Create a new instance.
Dim client As New Ftp()
‘ Connect to the FTP server.
client.Connect(“myserver”, 21, SecurityMode.Explicit)
‘ Authenticate.
client.Authenticate(“userName”, “password”)
‘ Do something here…
client.DownloadFile(“/my remote file.dat”, “my local file”)
‘ Disconnect.
client.Disconnect()

Implicit Connection with FTP

Originally, a separate port was assigned to the SSL version of the FTP. The port number 990 is usually assigned for FTP/SSL. Upon connection to this port, an SSL negotiation starts immediately and the control connection is secured. All data connections are also secured implicitly in the same way. This is similar to the approach used by HTTPS.

The code snippet below shows how to connect to an FTP server securely using Implicit security mode in Ultimate FTP.

C#  
// Create a new instance.
Ftp client = new Ftp();
// Connect to the FTP server.
client.Connect(“myserver”, 990, SecurityMode.Implicit);
// Authenticate.
client.Authenticate(“userName”, “password”);
// Do something here…
client.DownloadFile(“/my remote file.dat”, “my local file”);
// Disconnect.
client.Disconnect();

 

VB.NET  
‘ Create a new instance.
Dim client As New Ftp()
‘ Connect to the FTP server.
client.Connect(“myserver”, 990, SecurityMode.Implicit)
‘ Authenticate.
client.Authenticate(“userName”, “password”)
‘ Do something here…
client.DownloadFile(“/my remote file.dat”, “my local file”)
‘ Disconnect.
client.Disconnect()

Click here to download the Ultimate FTP Component for .NET, or here to download the .NET CF version.

Downloading multiple files and directories

Download multiple files and directories with UltimateFtp is really simple. You only need to call the DownloadFiles method with few parameters. The component will do the rest of hard work for you. It will loop through the specified directory, find files that match the specified search criteria, create threads, and start downloading. The steps belows show you how to use Ultimate FTP to download files with three threads.

Downloading files using multiple threads

1. Add using directives to your code to create aliases for existing namespaces and avoid having to type the fully qualified type names. The code looks similar to the following:

C#
using ComponentPro.Net;
using ComponentPro.IO;
VB.NET
Imports ComponentPro.Net
Imports ComponentPro.IO

2. Create a new instance of the Ftp class.

C#
// Create a new instance.
Ftp client = new Ftp();
VB.NET
‘ Create a new instance.
Dim client As New Ftp()

3. Register event handlers to the ThreadCompleted and ThreadsCompleted events to get informed when a thread has completed and all threads have completed. The code looks similar to the following:

C#
client.ThreadCompleted += client_ThreadCompleted;
client.ThreadsCompleted += client_ThreadsCompleted;
VB.NET
AddHandler client.ThreadCompleted, AddressOf client_ThreadCompleted
AddHandler client.ThreadsCompleted, AddressOf client_ThreadsCompleted

4. Now pass all needed parameters to the DownloadFiles method. The code looks similar to the following:

C#
// Download files and subdirectories from “/my folder” to “c:\my folder” using 3 threads. This waits untils these threads complete.
client.DownloadFiles(“/my folder”, “c:\my folder”, 3, true);
VB.NET
‘ Download files and subdirectories from “/my folder” to “c:\my folder” using 3 threads. This waits untils these threads complete.
client.DownloadFiles(“/my folder”“c:my folder”, 3, True)

Final example code

C#:

public void DoMultiThreadsDownloadFiles()
{
   // Create a new instance.
   Ftp client = new Ftp();
   // Connect to the server.
   client.Connect("server");
   // Authenticate.
   client.Authenticate("user", "pass");
   client.CommandResponse += client_ResponseRead;
   client.ThreadCompleted += client_ThreadCompleted;
   client.ThreadsCompleted += client_ThreadsCompleted;
   // ...
   // Download files and subdirectories from "/my folder" to "c:\\my folder" using 3 threads. This waits untils these threads complete.
   client.DownloadFiles("/my folder", "c:\\my folder", 3, true);
   // ...
   client.Disconnect();
}
void client_ThreadsCompleted(object sender, ThreadsCompletedEventArgs e)
{
   Console.WriteLine("Multi-threads file transfer completed");
}
void client_ThreadCompleted(object sender, ThreadCompletedEventArgs e)
{
   Console.WriteLine(string.Format("Thread ID {0} completed", e.FileSystem.ThreadId));
}
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);
}

VB.NET:

Public Sub DoMultiThreadsDownloadFiles()
    ' Create a new instance.
    Dim client As New Ftp()
    ' Connect to the server.
    client.Connect("server")
    ' Authenticate.
    client.Authenticate("user", "pass")
    AddHandler client.CommandResponse, AddressOf client_ResponseRead
    AddHandler client.ThreadCompleted, AddressOf client_ThreadCompleted
    AddHandler client.ThreadsCompleted, AddressOf client_ThreadsCompleted
    ' ...
    ' Download files and subdirectories from "/my folder" to "c:\\my folder" using 3 threads. This waits untils these threads complete.
    client.DownloadFiles("/my folder", "c:\my folder", 3, True)
    ' ...
    client.Disconnect()
End Sub
Private Sub client_ThreadsCompleted(ByVal sender As Object, ByVal e As ThreadsCompletedEventArgs)
    Console.WriteLine("Multi-threads file transfer completed")
End Sub
Private Sub client_ThreadCompleted(ByVal sender As Object, ByVal e As ThreadCompletedEventArgs)
    Console.WriteLine(String.Format("Thread ID {0} completed", e.FileSystem.ThreadId))
End Sub
Private 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

You may want to see other topics:

Uploading selected files and directories

Click here to download the Ultimate FTP Component for .NET, or here to download the .NET CF version.