Simple FTP Demo Application Using C#.NET 2.0

Introduction

An addition to the Microsoft .NET framework 2.0 to 1.x is the support for FTP. Earlier, you had to rely on third party libraries that pretty well suited most of your needs, but for sure, there is an extra pleasure using the .NET framework library classes. The code included is not designed to be a full-fledged reusable library, but rather an easy to use and reusable piece of code that is easily comprehensible and can be reused and tweaked to fit your specific needs. Therefore, the code for each functionality (upload, download, delete, and so forth) can be easily picked up separately and reused. The main motive behind this article was the unavailability of .NET 2.0 FTP sample codes and their usage in C#, maybe because it’s a new entrant to the .NET scenario, or the third party implementations available were working pretty well, that this area of the .NET 2.0 library hasn’t gotten enough focus.

Background

I started working on this FTP module as part of my official work, but the requirement soon changed, and I had to do it for .NET 1.1. So, I haven’t travelled deeper into the rabbit hole. But I believe this gives a good, instant start for using the FTP support in .NET 2.0.

Using the Code

Don’t forget to add the following directive:


using System.Net;
using System.IO;

The following steps can be considered as a generic procedure of getting an FTP request executed using the FtpWebRequest object:


  1. Create an FtpWebRequest object over an FTP server Uri.
  2. Set the FTP method to execute (upload, download, and so forth).
  3. Set options (SSL support, transfer as binary/not, and so on) for the FTP webrequest.
  4. Set the login credentials (username, password).
  5. Execute the request.
  6. Receive the response stream (if required).
  7. Close the FTP request, in addition to any open streams.

One point to watch out when coding for any FTP application is to have the settings for the FTP request proper to suit the FTP server and its specific configurations. The FtpWebRequest object exposes many properties to have these settings in place.

Setting Up the Upload Functionality

First, a URI is created; it represents the FTP address along with the filename (directory structure included). This URI is used to create the FtpWebRequest instance.

Then, properties of the FtpWebRequest object are set; these determine the settings for the FTP request. Some of its important properties are:


  • Credentials: Specifies the username and password to log in to the FTP server.

  • KeepAlive: Specifies whether the control connection should be closed after the request is completed. By default, it is set to true.

  • UseBinary: Denotes the datatype for file transfers. The two modes of file transfer in this case are Binary and ASCII. At bit level, both vary in the eighth bit of a byte. ASCII uses the eighth bit as an insignificant bit for error control, whereas for binary all eight bits are significant. So, take care when you go for the ASCII transmission. To be simple, all those files that open and read well in Notepad are safe as ASCII. Executables, formatted docs, and the like should be sent using binary mode. Sending ASCII files as binary works fine most of the time.

  • UsePassive: Specifies whether to use either active or passive mode. Earlier, active FTP worked fine with all clients, but now, as most of the random ports are blocked by a firewall, the active mode may fail. The passive FTP is helpful in this case. But still, it causes issues at the server. The higher ports requested by client on server may also be blocked by a firewall. But, because FTP servers will need to make their servers accessible to the greatest number of clients, they will almost certainly need to support passive FTP. Passive mode is considered safe because it ensures all data flow initiation comes from inside (client) the network rather than from the outside (server).

  • Contentlength: Setting this property is useful for the server you request to but is not of much use for you (client) because FtpWebRequest usually ignores this property value, so it will not be available for your use in most cases. But, if you set this property, the FTP server will get an advance idea about the size of the file it should expect (in case of an upload).

  • Method: Denotes what action (command) to take in the current request (upload, download, filelist, and the like). It is set a value defined in the WebRequestMethods.Ftp structure.

private void Upload(string filename)
{
   FileInfo fileInf = new FileInfo(filename);
   string uri = "ftp://" + ftpServerIP + "/" + fileInf.Name;
   FtpWebRequest reqFTP;

   // Create FtpWebRequest object from the Uri provided
   reqFTP = (FtpWebRequest)FtpWebRequest.Create
            (new Uri("ftp://" + ftpServerIP + "/" + fileInf.Name));

   // Provide the WebPermission Credintials
   reqFTP.Credentials = new NetworkCredential(ftpUserID, ftpPassword);

   // By default KeepAlive is true, where the control connection
   // is not closed after a command is executed.
   reqFTP.KeepAlive = false;

   // Specify the command to be executed.
   reqFTP.Method = WebRequestMethods.Ftp.UploadFile;

   // Specify the data transfer type.
   reqFTP.UseBinary = true;

   // Notify the server about the size of the uploaded file
   reqFTP.ContentLength = fileInf.Length;

   // The buffer size is set to 2kb
   int buffLength = 2048;
   byte[] buff = new byte[buffLength];
   int contentLen;

   // Opens a file stream (System.IO.FileStream) to read the file
   // to be uploaded
   FileStream fs = fileInf.OpenRead();

   try
   {
      // Stream to which the file to be upload is written
      Stream strm = reqFTP.GetRequestStream();

      // Read from the file stream 2kb at a time
      contentLen = fs.Read(buff, 0, buffLength);

      // Till Stream content ends
      while (contentLen != 0)
      {
         // Write Content from the file stream to the FTP Upload
         // Stream
         strm.Write(buff, 0, contentLen);
         contentLen = fs.Read(buff, 0, buffLength);
      }

      // Close the file stream and the Request Stream
      strm.Close();
      fs.Close();
   }
   catch(Exception ex)
   {
      MessageBox.Show(ex.Message, "Upload Error");
   }
}

Above is a sample code for FTP Upload (PUT). The underlying sub command used is STOR. Here, an FtpWebRequest object is made for the specified file on the FTP server. Different properties are set for the request, namely Credentials, KeepAlive, Method, UseBinary, and ContentLength.

The file in your local machine is opened and the contents are written to the FTP request stream. Here, a 2Kb buffer is used as an appropriate size suited for upload of larger or smaller files.

private void Download(string filePath, string fileName)
{
   FtpWebRequest reqFTP;
   try
   {
      //filePath: The full path where the file is to be created.
      //fileName: Name of the file to be createdNeed not name on
      //          the FTP server. name name()
      FileStream outputStream = new FileStream(filePath + "\\" +
         fileName, FileMode.Create);

      reqFTP = (FtpWebRequest)FtpWebRequest.Create(new Uri("ftp://"
         + ftpServerIP + "/" + fileName));
      reqFTP.Method = WebRequestMethods.Ftp.DownloadFile;
      reqFTP.UseBinary = true;
      reqFTP.Credentials = new NetworkCredential(ftpUserID,
                                                 ftpPassword);
      FtpWebResponse response = (FtpWebResponse)reqFTP.GetResponse();
      Stream ftpStream = response.GetResponseStream();
      long cl = response.ContentLength;
      int bufferSize = 2048;
      int readCount;
      byte[] buffer = new byte[bufferSize];

      readCount = ftpStream.Read(buffer, 0, bufferSize);
      while (readCount > 0)
      {
         outputStream.Write(buffer, 0, readCount);
         readCount = ftpStream.Read(buffer, 0, bufferSize);
      }

      ftpStream.Close();
      outputStream.Close();
      response.Close();
   }
   catch (Exception ex)
   {
      MessageBox.Show(ex.Message);
   }
}

Above is a sample code to download a file from the FTP server. Unlike the Upload functionality described above, Download would require the response stream, which will contain the content of the file requested.

More by Author

Get the Free Newsletter!

Subscribe to Developer Insider for top news, trends & analysis

Must Read