Home About

February 23rd, 2009

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

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:

3 Responses 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?

  2. Darren Lee Says:

    Hi,

    I think it’s really brilliant and such a professional class you wrote, it’s helpful for my current project, I’ve looked for it for a long while, thanks for your sharing.

    One suggestion, I think the BasicFTPClient still needs one more function which enables user to browse all the files that are stored in a certain FTP folder, so that users would not have to type in an exact title of the file that he/she wants to download, hopefully it would make the class going perfect.

    Thanks again for your knowledge shared.

  3. andylu Says:

    it’s wonderful..!!!!! thanks for the code…. 100% correct


Most popular

    Sorry. No data so far.

Recent Comments
  • Juan Romero: Hi there, it’s a neat little class, but I believe you could do the same thing with the WebClient...
  • anthosh: Hey, THank you very much for your tutorial. It was awesome. But i have a problem that i am not able to...
  • bian: how to get passphase if i have encrypt and decrypt string?? Thanks alot
  • Michael: Hi, I really like your post, thanks a lot, it really helped clear up a few things I could not remember how...
  • Bharat Prajapati: i was trying to import keyword dictionary to this plugin which is in csv format, but i get an error...