Learning never exhausts the mind

Last Updated by

How to use the FtpWebRequest and FtpWebResponse classes to create a FTP utility class which will allow us to retrieve a directory listing, download files, upload files and delete files.

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.

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.

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

FTP Directory Listing Function

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

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:

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.

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.

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.

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:

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.

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

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();
        }
    }
}
7 thoughts on “Ultimate Guide to FTP using C#
  • 3rd October 2018 at 12:00 am

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

    Reply
  • 7th November 2017 at 12:00 am

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

    Reply
  • 22nd March 2016 at 12:00 am

    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.

    Reply
  • 16th September 2014 at 12:00 am

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

    Reply
  • Santiago
    5th April 2014 at 12:00 am

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

    Reply
  • Santiago
    5th April 2014 at 12:00 am

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

    Reply

Leave a Reply

Fields marked with * are mandatory.

We respect your privacy, and will not make your email public. Hashed email address may be checked against Gravatar service to retrieve avatars. This site uses Akismet to reduce spam. Learn how your comment data is processed.