Using FTP with Microsoft.NET

Generally when data is retrieved from a 3rd party the 3rd party uses some sort of FTP to host the data. This post will attempt to go over the basics of connected to different FTP servers with C# to download a file.

There are 4 main types of FTP:

  • FTP – This is plain old unencrypted FTP, normally over port 21.
  • FTP over explicit SSL – This is an encrypted form of FTP where initially the client connects over an unsecured channel (usually port 21) and then a secure channel is requested by the client or server.
  • FTP over implicit SSL – This is an encrypted form of FTP where the server must listen on a different port for encrypted traffic (normally port 990).
  • SFTP – This is more of an SSH connection with file transferring commands rather than a different version of FTP.

As a side note I found the terms explicit SSL and implicit SSL rather confusing at first, until I realized the terms are from the point of view of the protocol. With explicit SSL either the client or the server must explicitly request for a secure channel. Since implicit SSL the connection is always encrypted based on the connected port.

Using FTP or FTP over explicit SSL with .NET is fairly straight forward using the FtpRequest object.


// Setup the FTP request object
FtpWebRequest ftpRequest =
(FtpWebRequest)FtpWebRequest.Create("ftp://localhost/file.txt");
// Supply credentials
ftpRequest.Credentials =
new NetworkCredential("username", "***p@ssw0rd***");
// To use FTP over explict SSL set EnableSsl to true
// otherwise plain unencrypted FTP will be used
ftpRequest.EnableSsl = true;

// Download the file
using (WebResponse ftpResponse = ftpRequest.GetResponse())
using (Stream file = ftpResponse.GetResponseStream())
using (StreamReader reader = new StreamReader(file))
{
Console.WriteLine("File contents: {0}", reader.ReadToEnd());
}

Using FTP over implicit SSL is not quite as straightforward, but it can be done in .NET without the use of any 3rd party software. Since implicit SSL is basically FTP commands done over an SSL connection we just need to setup an SSL connection with .NET, then issue the commands we need to download the file.


// Open a connection to the server over port 990
// (default port for FTP over implicit SSL)
using (TcpClient client = new TcpClient("localhost", 990))
using (SslStream sslStream = new SslStream(client.GetStream(), true))
{
// Start SSL/TLS Handshake
sslStream.AuthenticateAsClient("localhost");

// Setup a delegate for writing FTP commands to the SSL stream
Action WriteCommand = delegate(string command)
{
byte[] commandBytes =
Encoding.ASCII.GetBytes(command + Environment.NewLine);
sslStream.Write(commandBytes, 0, commandBytes.Length);
};

// Write raw FTP commands to the SSL stream
WriteCommand(“USER username”);
WriteCommand(“PASS ***p@ssw0rd***”);


// Connect to data port to download the file
}

The code to actually download the file becomes slightly more complicated because the file needs to be downloaded a data connection. How the data connection will be setup depend on whether the connection is passive or active. Either way a data connection with implicit SSL can be setup the same way using a TcpClient and an SslStream. How to actually connect to the data port is beyond the scope of this post.

Using SFTP with straight .NET becomes more complicated. I have not found it worthwhile to try to setup SFTP without the use of a third party tool. If anyone knows of an easy way to do this feel free to let me know.

Sources

One Response to “Using FTP with Microsoft.NET”

  1. Balram says:

    Great Post!
    Helped me to connect to my FTP server with explicit TLS encryption.

    Can you please let me know how to read file size over the same server?

    I am able to download file but when I’m setting method to GetFileSize, it’s throwing error 550.

    Thanks again!

    private long GetFileSize(string downloadUrl, string ftpUserName, string ftpPassword)
    {
    long fileSize = -1;
    try
    {
    FtpWebRequest request = (FtpWebRequest)FtpWebRequest.Create(new Uri(downloadUrl));
    request.Credentials = new NetworkCredential(ftpUserName, ftpPassword);
    request.EnableSsl = true;
    request.Method = WebRequestMethods.Ftp.GetFileSize;
    FtpWebResponse response = (FtpWebResponse)request.GetResponse();
    long size = response.ContentLength;
    response.Close();
    }
    catch (Exception exception)
    {
    MessageBox.Show(exception.Message);
    }
    return fileSize;
    }

Leave a Reply