Ultimate Guide to Working With FTP using C#

How to use the FtpWebRequest and FtpWebResponse classes to to retrieve a directory listing, download files, upload files and delete files.

By Tim Trott | C# ASP.Net MVC | January 28, 2010
1,447 words, estimated reading time 5 minutes.

I'm going to create a utility class during this tutorial which contains a series of methods to perform using FTP. You can copy and paste into your project, or adapt to suit your needs.

I'm basing this on a console application with an extra class file called FTPUtility.cs. All this code goes inside that file.

Creating the FTPClient Class

The first thing I have done is to create a set of private fields that need to be populated from the constructor.

C#
using System;
using System.Collections.Generic;
using System.Text;
using System.Net;
using System.IO;

namespace Utils
{
    public class FTPClient
    {
        / The hostname or IP address of the FTP server
        private string _remoteHost;

        / The remote username
        private string _remoteUser;
        
        / Password for the remote user
        private string _remotePass;
    }
}

The constructor for this class takes in the connection properties for the remote host.

C#
public FTPClient(string remoteHost, string remoteUser, string remotePassword)
{
    _remoteHost = remoteHost;
    _remoteUser = remoteUser;
    _remotePass = remotePassword;
}

FTP using C# - Directory Listing Function

The first thing we are going to look at is establishing a connection to the server and retrieving a file list.

C#
public List<string> DirectoryListing()
{
    FtpWebRequest request = (FtpWebRequest)WebRequest.Create(_remoteHost);
    request.Method = WebRequestMethods.Ftp.ListDirectory;
    request.Credentials = new NetworkCredential(_remoteUser, _remotePass);
    FtpWebResponse response = (FtpWebResponse)request.GetResponse();
    Stream responseStream = response.GetResponseStream();
    StreamReader reader = new StreamReader(responseStream);

    List<string> result = new List<string>();

    while (!reader.EndOfStream)
    {
        result.Add(reader.ReadLine());
    }

    reader.Close();
    response.Close();
    return result;
}

If I run this over my test site with the following code:

C#
namespace FTPTestApplication
{
    class Program
    {
        static void Main(string[] args)
        {
            Utils.FTPClient client = new Utils.FTPClient("ftp:/localhost", "ftpUser", "ftpPass");
            List<string> files = client.DirectoryListing();
            foreach (string s in files)
            {
                Console.WriteLine(s);
            }
            Console.ReadLine();
        }
    }
}

The result is:

.cshrc
.imap
.login
.login_conf
.mail_aliases
.mailrc
.profile
.rhosts
.shrc
backup
boxes
log_config
public_html
www_logs

Now the next logical step is to navigate to a folder, this can be done by amending the parameter to the WebRequest.Create method. I have created an overloaded method so that we can browse the root or into a given folder.

C#
public List<string> DirectoryListing()
{
    return DirectoryListing(string.Empty);
}

public List<string> DirectoryListing(string folder)
{
    FtpWebRequest request = (FtpWebRequest)WebRequest.Create(_remoteHost + folder);
    request.Method = WebRequestMethods.Ftp.ListDirectory;
    request.Credentials = new NetworkCredential(_remoteUser, _remotePass);
    FtpWebResponse response = (FtpWebResponse)request.GetResponse();
    Stream responseStream = response.GetResponseStream();
    StreamReader reader = new StreamReader(responseStream);

    List<string> result = new List<string>();

    while (!reader.EndOfStream)
    {
        result.Add(reader.ReadLine());
    }

    reader.Close();
    response.Close();
    return result;
}

I can now add directory information to the original call to look inside a folder.

C#
Utils.FTPClient client = new Utils.FTPClient("ftp:/localhost/public_html/", "ftpUser", "ftpPass");

Downloading a File with our FTPClient

The next task is to download a file from the server to our PC. This is done in much the same way as directory listings.

C#
public void Download(string file, string destination)
{
    FtpWebRequest request = (FtpWebRequest)WebRequest.Create(_remoteHost + file);
    request.Method = WebRequestMethods.Ftp.DownloadFile;
    request.Credentials = new NetworkCredential(_remoteUser, _remotePass);
    FtpWebResponse response = (FtpWebResponse)request.GetResponse();
    Stream responseStream = response.GetResponseStream();
    StreamReader reader = new StreamReader(responseStream);

    StreamWriter writer = new StreamWriter(destination);
    writer.Write(reader.ReadToEnd());

    writer.Close();
    reader.Close();
    response.Close();
}

To call this method use:

C#
Utils.FTPClient client = new Utils.FTPClient("ftp:/localhost/public_html/", "ftpUser", "ftpPass");
client.Download("test.zip", "c:test.zip");

Hopefully, you can start to see a pattern forming when using FtpWebRequest methods. In fact, all the code is pretty similar regardless of what action you are performing. The WebRequestMethods.Ftp enum contains a list of actions you can perform. These include:

  • AppendFile - Append a file to an existing file on an FTP server (FTP APPE)
  • DeleteFile - Delete a file on an FTP server (FTP DELE)
  • DownloadFile - Download a file from an FTP server (FTP RETR)
  • GetFileSize - Retrieve the size of a file on an FTP server (FTP SIZE)
  • ListDirectory - Gets a short listing of the files on an FTP server (FTP NLIST)
  • ListDirectoryDetails - Gets a detailed listing of the files on an FTP server (FTP LIST)
  • MakeDirectory - Creates a directory on an FTP server (FTP MKD)
  • RemoveDirectory - Method that removes a directory (FTP RM)
  • Rename - Renames a directory (FTP RENAME)
  • UploadFile - Uploads a file to an FTP server (FTP STOR)
  • UploadFileWithUniqueName - Uploads a file with a unique name to an FTP server (FTP STOU)

Uploading a File through FTPClient

The final example I am going to show is how to upload a file to the server. This method differs slightly as we need to create a StreamReader to read the source file.

C#
public void UploadFile(string FullPathFilename)
{
    string filename = Path.GetFileName(FullPathFilename);

    FtpWebRequest request = (FtpWebRequest)WebRequest.Create(_remoteHost + filename);
    request.Method = WebRequestMethods.Ftp.UploadFile;
    request.Credentials = new NetworkCredential(_remoteUser, _remotePass);

    StreamReader sourceStream = new StreamReader(FullPathFilename);
    byte[] fileContents = Encoding.UTF8.GetBytes(sourceStream.ReadToEnd());

    request.ContentLength = fileContents.Length;

    Stream requestStream = request.GetRequestStream();
    requestStream.Write(fileContents, 0, fileContents.Length);

    FtpWebResponse response = (FtpWebResponse)request.GetResponse();

    response.Close();
    requestStream.Close();
    sourceStream.Close();
}

And that's all there is to it.

Just a few points to remember:

  • WebRequest.Create takes the full URL including path and file name. To work with a file specify the full path name e.g. ftp:/localhost/folder/test/myfile.zip.
  • To work with a folder/directory, specify the full path e.g. ftp:/localhost/folder/test/
  • You cannot upload a file to ftp:/localhost/folder/test/, you have to specify the filename when you create the WebRequest.

FTPClient Code in Full

C#
using System;
using System.Collections.Generic;
using System.Text;
using System.Net;
using System.IO;

namespace Utils
{
    public class FTPClient
    {
        / The hostname or IP address of the FTP server
        private string _remoteHost;

        / The remote username
        private string _remoteUser;

        / Password for the remote user
        private string _remotePass;

        public FTPClient(string remoteHost, string remoteUser, string remotePassword, bool debug)
        {
            _remoteHost = remoteHost;
            _remoteUser = remoteUser;
            _remotePass = remotePassword;
        }

        // <summary>
        // Get a list of files and folders on the FTP server
        // </summary>
        // <returns></returns>
        public List<string> DirectoryListing()
        {
            return DirectoryListing(string.Empty);
        }

        // <summary>
        // List files and folders in a given folder on the server
        // </summary>
        // <param name="folder"></param>
        // <returns></returns>
        public List<string> DirectoryListing(string folder)
        {
            FtpWebRequest request = (FtpWebRequest)WebRequest.Create(_remoteHost + folder);
            request.Method = WebRequestMethods.Ftp.ListDirectory;
            request.Credentials = new NetworkCredential(_remoteUser, _remotePass);
            FtpWebResponse response = (FtpWebResponse)request.GetResponse();
            Stream responseStream = response.GetResponseStream();
            StreamReader reader = new StreamReader(responseStream);

            List<string> result = new List<string>();

            while (!reader.EndOfStream)
            {
                result.Add(reader.ReadLine());
            }

            reader.Close();
            response.Close();
            return result;
        }

        // <summary>
        // Download a file from the FTP server to the destination
        // </summary>
        // <param name="filename">filename and path to the file, e.g. public_html/test.zip</param>
        // <param name="destination">The location to save the file, e.g. c:test.zip</param>
        public void Download(string filename, string destination)
        {
            FtpWebRequest request = (FtpWebRequest)WebRequest.Create(_remoteHost + filename);
            request.Method = WebRequestMethods.Ftp.DownloadFile;
            request.Credentials = new NetworkCredential(_remoteUser, _remotePass);
            FtpWebResponse response = (FtpWebResponse)request.GetResponse();
            Stream responseStream = response.GetResponseStream();
            StreamReader reader = new StreamReader(responseStream);

            StreamWriter writer = new StreamWriter(destination);
            writer.Write(reader.ReadToEnd());

            writer.Close();
            reader.Close();
            response.Close();
        }

        // <summary>
        // Remove a file from the server.
        // </summary>
        // <param name="filename">filename and path to the file, e.g. public_html/test.zip</param>
        public void DeleteFileFromServer(string filename)
        {
            FtpWebRequest request = (FtpWebRequest)WebRequest.Create(_remoteHost + filename);
            request.Method = WebRequestMethods.Ftp.DeleteFile;
            request.Credentials = new NetworkCredential(_remoteUser, _remotePass);
            FtpWebResponse response = (FtpWebResponse)request.GetResponse();
            response.Close();
        }

        // <summary>
        // Upload a file to the server
        // </summary>
        // <param name="source">Full path to the source file e.g. c:test.zip</param>
        // <param name="destination">destination folder and filename e.g. public_html/test.zip</param>
        public void UploadFile(string source, string destination)
        {
            string filename = Path.GetFileName(source);

            FtpWebRequest request = (FtpWebRequest)WebRequest.Create(_remoteHost + destination);
            request.Method = WebRequestMethods.Ftp.UploadFile;
            request.Credentials = new NetworkCredential(_remoteUser, _remotePass);

            StreamReader sourceStream = new StreamReader(source);
            byte[] fileContents = Encoding.UTF8.GetBytes(sourceStream.ReadToEnd());

            request.ContentLength = fileContents.Length;

            Stream requestStream = request.GetRequestStream();
            requestStream.Write(fileContents, 0, fileContents.Length);

            FtpWebResponse response = (FtpWebResponse)request.GetResponse();

            response.Close();
            requestStream.Close();
            sourceStream.Close();
        }
    }
}
Was this article helpful to you?
 

Related ArticlesThese articles may also be of interest to you

CommentsShare your thoughts in the comments below

If you enjoyed reading this article, or it helped you in some way, all I ask in return is you leave a comment below or share this page with your friends. Thank you.

This post has 6 comment(s). Why not join the discussion!

We respect your privacy, and will not make your email public. Learn how your comment data is processed.

  1. EB

    On Wednesday 3rd of October 2018, Erich Baumgartner said

    Thank you for your contribution. It is very helpful for me. Can I realy download only files? What about directories?

  2. WA

    On Tuesday 7th of November 2017, Wasae said

    Getting This Exception While Uploading File on this Line Request.GetRequestStream() "The remote server returned an error: (500) Syntax error, command unrecognized"

  3. VL

    On Tuesday 22nd of March 2016, Vladislav said

    As I see there is no check for file consistancy on ftp.

    I mean next case. If some1 is uploading a big file on ftp and at this moment you start downloading it.
    This will cause you won't receive full file.

  4. MO

    On Tuesday 16th of September 2014, moses said

    I have a case to abort an ftpwebrequest download at any time during download operation. The process is synch and I am using (FtpWebResponse)ftpRequest.GetResponse() so I cannot use Ftpwebrequest.Abort();

  5. JD

    On Wednesday 23rd of April 2014, James Dennis said

    Please note that this will not work on compressed files. See http://stackoverflow.com/questions/16495735/zip-file-is-getting-corrupted-after-uploaded-to-server-using-c-sharp. Otherwise, thank you for your contribution. It was very helpful!

  6. SA

    On Saturday 5th of April 2014, Santiago said

    Thanks a lot, I'm building a project which involves ftp, and you just taught me the basics. Greets