Home About

February 23rd, 2009

Using the C# WebClient class to upload and download FTP files - 1

Your C# program has just calculated the weekly sales report and you need to upload it to the company file server. The C# System.Net.Webclient class makes this quite trivial. The same for downloading a file from the server and then parsing it for content. This post shows how you can use basic FTP actions to upload, download files and either store them in memory or write them to disk.

At the end of this post you will find my BasicFTPClient class that implements the uploading and downloading code.

1. Download an FTP file to disk

If you have a file called “fileonftpserver.txt” and would like to download it to “/tmp/mydownload.txt” use the “DownloadFile” method:

BasicFTPClient MyClient = new BasicFTPClient();

MyClient.Host="myserver.com";
MyClient.Username="yourusername";
MyClient.Password="yourpassword";

try
{
     MyClient.DownloadFile("fileonftpserver.txt","/tmp/mydownload.txt"); // c:\temp\mydownload.txt for Windows
}
catch (WebException e)
{
     Console.WriteLine(e.ToString());
}

2. Download an FTP file to memory

If you would like to directly process the file you have downloaded (and don’t need to save it to disk first) the “DownloadData” method is your friend. If you would like to print the contents of the file to the console you could try this:

BasicFTPClient MyClient = new BasicFTPClient();

MyClient.Host="myserver.com";
MyClient.Username="yourusername";
MyClient.Password="yourpassword";

try
{
    byte[] Data = MyClient.DownloadData("download.test");

    // Convert the data to a string
    String s = System.Text.Encoding.UTF8.GetString(Data);
    Console.WriteLine(s);
}
catch (WebException e)
{
    Console.WriteLine(e.ToString());
}

3. Upload a file to the FTP server

If you have a file on disk and would like to upload it to an FTP server then use the “UploadFile” method.

BasicFTPClient MyClient = new BasicFTPClient();

MyClient.Host="myserver.com";
MyClient.Username="yourusername";
MyClient.Password="yourpassword";

try
{
    MyClient.UploadFile("upload.test","/tmp/output.txt");
}
catch (WebException e)
{
    Console.WriteLine(e.ToString());
}

4. Upload a byte[] to the FTP server

The “UploadData” method takes a byte array as the source of its data, allowing you to create something in memory and then save it to an FTP server. Usefull for those reports you have just generated.

BasicFTPClient MyClient = new BasicFTPClient();

MyClient.Host="myserver.com";
MyClient.Username="yourusername";
MyClient.Password="yourpassword";

try
{
    string MyReport = "Sales figures for October 2010";
    byte[] Data = System.Text.Encoding.UTF8.GetBytes(MyReport);
    MyClient.UploadData("upload.test",Data);
}
catch (WebException e)
{
    Console.WriteLine(e.ToString());
}

The Mono angle

All of the above examples work on Mono just as well as on Microsoft’s .NET. With a catch: I found two bugs in the Mono class libraries that made things quite impossible. Both were fixed by the mono team within hours of reporting them (thanks!). So if you are using the Mono CVS code for Mono 2.4 you are in luck, otherwise the following code is not going to work until the next Mono release.

If you come across a problem with Mono reporting a bug is trivial, you can report them at bugzilla.novell.com

The BasicFTPClient class

using System;
using System.Net;
using System.IO;

namespace BasicFTPClientNamespace
{
    class BasicFTPClient
    {
        public string Username;
        public string Password;
        public string Host;
        public int Port;

        public BasicFTPClient()
        {
            Username = "anonymous";
            Password = "anonymous@internet.com";
            Port = 21;
            Host = "";
        }

        public BasicFTPClient(string theUser, string thePassword, string theHost)
        {
            Username = theUser;
            Password = thePassword;
            Host = theHost;
            Port = 21;
        }

        private Uri BuildServerUri(string Path)
        {
            return new Uri(String.Format("ftp://{0}:{1}/{2}", Host, Port, Path));
        }

        /// <summary>
        /// This method downloads the given file name from the FTP server
        /// and returns a byte array containing its contents.
        /// Throws a WebException on encountering a network error.
        /// </summary>

        public byte[] DownloadData(string path)
        {
            // Get the object used to communicate with the server.
            WebClient request = new WebClient();

            // Logon to the server using username + password
            request.Credentials = new NetworkCredential(Username, Password);
            return request.DownloadData(BuildServerUri(path));
        }

        /// <summary>
        /// This method downloads the FTP file specified by "ftppath" and saves
        /// it to "destfile".
        /// Throws a WebException on encountering a network error.
        /// </summary>
        public void DownloadFile(string ftppath, string destfile)
        {
            // Download the data
            byte[] Data = DownloadData(ftppath);

            // Save the data to disk
            FileStream fs = new FileStream(destfile, FileMode.Create);
            fs.Write(Data, 0, Data.Length);
            fs.Close();
        }

        /// <summary>
        /// Upload a byte[] to the FTP server
        /// </summary>
        /// <param name="path">Path on the FTP server (upload/myfile.txt)</param>
        /// <param name="Data">A byte[] containing the data to upload</param>
        /// <returns>The server response in a byte[]</returns>

        public byte[] UploadData(string path, byte[] Data)
        {
            // Get the object used to communicate with the server.
            WebClient request = new WebClient();

            // Logon to the server using username + password
            request.Credentials = new NetworkCredential(Username, Password);
            return request.UploadData(BuildServerUri(path), Data);
        }
        
        /// <summary>
        /// Load a file from disk and upload it to the FTP server
        /// </summary>
        /// <param name="ftppath">Path on the FTP server (/upload/myfile.txt)</param>
        /// <param name="srcfile">File on the local harddisk to upload</param>
        /// <returns>The server response in a byte[]</returns>

        public byte[] UploadFile(string ftppath, string srcfile)
        {
            // Read the data from disk
            FileStream fs = new FileStream(srcfile, FileMode.Open);
            byte[] FileData = new byte[fs.Length];

            int numBytesToRead = (int)fs.Length;
            int numBytesRead = 0;
            while (numBytesToRead > 0)
            {
                // Read may return anything from 0 to numBytesToRead.
                int n = fs.Read(FileData, numBytesRead, numBytesToRead);

                // Break when the end of the file is reached.
                if (n == 0) break;

                numBytesRead += n;
                numBytesToRead -= n;
            }
            numBytesToRead = FileData.Length;
            fs.Close();

            // Upload the data from the buffer
            return UploadData(ftppath, FileData);
        }

    }
}
Be Sociable, Share!

Tags:

One Response to “Using the C# WebClient class to upload and download FTP files”

  1. Rohit Prakash Says:

    Thanks for the code. I needed it urgently.

    Do you have any idea of determining the file version of any file located on a remote server?


Most popular
Recent Comments
  • ARS: great plugin! I love it! but, it will be so nice if you can add attribute ‘title’ as one of...
  • Nelson: Saved me from doing it myself. Good article.
  • andy: i am currently playing taiwanese server wow in 奈辛瓦里(PVP) and i would like to realm transfer to somewhere there...
  • berties: any english speaking playing on a taiwanese server?
  • web application development: has C# search volume really so constant over the years? really surprising.