ASP.NET FTP with SSL

Friday Apr 11th 2008 by Jereme Guenther
Share:

This code snippet and document show how to connect to an FTP server with SSL enabled using ASP.NET. The code is written in C#.NET.

I recently needed to connect to a remote FTP server using SSL and C#.NET. I discovered that there were few good examples on the web pertaining to FTP. Part of this was because the .NET framework didn't seem to support FTP very well until version 2.0. Even in version 2.0, it gives only the raw tools needed to put together a basic FTP client; it doesn't have any upload, download, and the like pre-written.

After spending about a day browsing the web and cobbling together a class that acted as a sort of wrapper to give me something easier to work with, I thought I would share it. Although I did find one good example for uploading and one good example for deleting files on an FTP server, I couldn't find one complete source that had it all. Also, I couldn't find any source that had a working SSL implementation.

What I have here is a very rough starter class that has just passed the first phase of testing. I intend it only to help others get up and running; if you are planning on using it, it really needs a lot more error checking and features. Hopefully, I will have time later to come back and update this article with some more solid code.

using System;
using System.Collections.Generic;
using System.Text;
using System.Net;
using System.IO;
using System.Security.Cryptography.X509Certificates;
using System.Net.Security;

namespace FtpFramework
{
   public class FTP
   {
      public string UserName   = "";
      public string Password   = "";
      public bool KeepAlive    = false;
      public bool UseSSL       = true;
      private string m_FTPSite = "";
      public string FTPSite
      {
         get { return m_FTPSite; }
         set
         {
            m_FTPSite = value;
            if (!m_FTPSite.EndsWith("/")) m_FTPSite += "/";
         }
      }
      private string m_CurDir = "";
      public string CurrentDirectory
      {
         get { return m_CurDir; }
         set
         {
            m_CurDir = value;
            if (!m_CurDir.EndsWith("/") && m_CurDir != "")
               m_CurDir += "/";
               m_CurDir = m_CurDir.TrimStart("/".ToCharArray());
         }
      }

      public FTP() { }
      public FTP(string sFTPSite, string sUserName,
                 string sPassword)
      {
         UserName = sUserName;
         Password = sPassword;
         FTPSite = sFTPSite;
      }

      public static bool ValidateServerCertificate(object sender,
         X509Certificate certificate, X509Chain chain,
         SslPolicyErrors sslPolicyErrors)
      {
         if (sslPolicyErrors ==
            SslPolicyErrors.RemoteCertificateChainErrors) {
            return false;
         } else if (sslPolicyErrors ==
            SslPolicyErrors.RemoteCertificateNameMismatch) {
            System.Security.Policy.Zone z =
               System.Security.Policy.Zone.CreateFromUrl
               (((HttpWebRequest)sender).RequestUri.ToString());
            if (z.SecurityZone ==
               System.Security.SecurityZone.Intranet ||
               z.SecurityZone ==
               System.Security.SecurityZone.MyComputer) {
               return true;
            }
            return false;
         }
         return true;
      }

      public List<string> GetFileList(string CurDirectory,
         string StartsWith, string EndsWith)
      {
         CurrentDirectory = CurDirectory;
         return GetFileList(StartsWith, EndsWith);
      }
      public List<string> GetFileList(string StartsWith,
                                      string EndsWith)
      {
         FtpWebRequest oFTP =
            (FtpWebRequest)FtpWebRequest.Create(FTPSite +
            CurrentDirectory);
         //oFTP.EnableSsl = true;
         oFTP.Credentials  = new NetworkCredential(UserName,
                                                   Password);
         oFTP.KeepAlive    = KeepAlive;
         oFTP.EnableSsl    = UseSSL;
         // Validate the server certificate with
         // ServerCertificateValidationCallBack
         if (UseSSL) ServicePointManager.
            ServerCertificateValidationCallback =
            new RemoteCertificateValidationCallback
            (ValidateServerCertificate);
         //System.Security.Cryptography.X509Certificates.
         //X509Certificate oCert = new System.Security.Cryptography.
         //X509Certificates.X509Certificate();
         //oFTP.ClientCertificates.Add(oCert);

         oFTP.Method = WebRequestMethods.Ftp.ListDirectory;
         FtpWebResponse response =
            (FtpWebResponse)oFTP.GetResponse();
         StreamReader sr =
            new StreamReader(response.GetResponseStream());
         string str = sr.ReadLine();
         List<string> oList = new List<string>();
         while (str != null) {
            if (str.StartsWith(StartsWith) &&
               str.EndsWith(EndsWith)) oList.Add(str);
            str = sr.ReadLine();
         }
         sr.Close();
         response.Close();
         oFTP = null;

         return oList;
      }

      public bool GetFile(string Name, string DestFile)
      {
         //1. Create a request: must be in ftp://hostname format,
         //   not just ftp.myhost.com
         FtpWebRequest oFTP = (FtpWebRequest)FtpWebRequest.
            Create(FTPSite + CurrentDirectory + Name);
         //oFTP.EnableSsl = true;
         //2. Set credentials
         oFTP.Credentials = new NetworkCredential(UserName,
                                                  Password);
         //Define the action required (in this case, download
         //                            a file)
         oFTP.Method = WebRequestMethods.Ftp.DownloadFile;

         //3. Settings
         oFTP.KeepAlive = KeepAlive;
         oFTP.EnableSsl = UseSSL;
         // Validate the server certificate with
         // ServerCertificateValidationCallBack
         if (UseSSL) ServicePointManager.
            ServerCertificateValidationCallback = new
            RemoteCertificateValidationCallback
            (ValidateServerCertificate);
         //we want a binary transfer, not textual data
         oFTP.UseBinary = true;

         //4. If we were using a method that uploads data;
         //   for example, UploadFile, we would open the
         //   ftp.GetRequestStream here an send the data

         //5. Get the response to the Ftp request and the
         //   associated stream
         FtpWebResponse response =
            (FtpWebResponse)oFTP.GetResponse();
         Stream responseStream = response.GetResponseStream();
         //loop to read & write to file
         FileStream fs = new FileStream(DestFile, FileMode.Create);
         Byte[] buffer = new Byte[2047];
         int read = 1;
         while (read != 0) {
            read = responseStream.Read(buffer, 0, buffer.Length);
            fs.Write(buffer, 0, read);
         }    //see Note(1)
         responseStream.Close();
         fs.Flush();
         fs.Close();
         responseStream.Close();
         response.Close();
         oFTP = null;

         return true;
      }

      public bool UploadFile(FileInfo oFile)
      {
         FtpWebRequest ftpRequest;
         FtpWebResponse ftpResponse;

         try {
            //Settings required to establish a connection with
            //the server
            ftpRequest = (FtpWebRequest)FtpWebRequest.
               Create(FTPSite + CurrentDirectory + oFile.Name);
            ftpRequest.Method = WebRequestMethods.Ftp.UploadFile;
            ftpRequest.Proxy = null;
            ftpRequest.UseBinary = true;
            ftpRequest.Credentials =
               new NetworkCredential(UserName, Password);
            ftpRequest.KeepAlive = KeepAlive;
            ftpRequest.EnableSsl = UseSSL;
            // Validate the server certificate with
            // ServerCertificateValidationCallBack
            if (UseSSL) ServicePointManager.
               ServerCertificateValidationCallback = new
                  RemoteCertificateValidationCallback
                  (ValidateServerCertificate);

            //Selection of file to be uploaded
            byte[] fileContents = new byte[oFile.Length];

            //will destroy the object immediately after being used
            using (FileStream fr = oFile.OpenRead()) {
               fr.Read(fileContents, 0,
               Convert.ToInt32(oFile.Length));
            }
            using (Stream writer = ftpRequest.GetRequestStream()) {
               writer.Write(fileContents, 0, fileContents.Length);
            }
            //Gets the FtpWebResponse of the uploading operation
            ftpResponse = (FtpWebResponse)ftpRequest.GetResponse();
            //Display response
            //Response.Write(ftpResponse.StatusDescription);

            ftpResponse.Close();
            ftpRequest = null;

            return true;
         }
         catch (WebException webex) {
            return false;
            //this.Message = webex.ToString();
         }
      }

      public bool DeleteFile(string Name)
      {
      //1. Create a request: must be in ftp://hostname format,
      //   not just ftp.myhost.com
      FtpWebRequest oFTP = (FtpWebRequest)FtpWebRequest.
         Create(FTPSite + CurrentDirectory + Name);
      //oFTP.EnableSsl = true;
      //2. Set credentials
      oFTP.Credentials = new NetworkCredential(UserName, Password);
      //Define the action required (in this case, download a file)
      oFTP.Method = WebRequestMethods.Ftp.DeleteFile;

      //3. Settings
      oFTP.KeepAlive = KeepAlive;
      oFTP.EnableSsl = UseSSL;
      // Validate the server certificate with
      // ServerCertificateValidationCallBack
      if (UseSSL) ServicePointManager.
         ServerCertificateValidationCallback = new
         RemoteCertificateValidationCallback
         (ValidateServerCertificate);
      //we want a binary transfer, not textual data
      oFTP.UseBinary = true;

      //4. If we were using a method that uploads data;
      //   for example, UploadFile, we would open the
      // ftp.GetRequestStream here an send the data

      //5. Get the response to the Ftp request and the associated
      //   stream
      FtpWebResponse response = (FtpWebResponse)oFTP.GetResponse();
      FtpStatusCode oStat = response.StatusCode;
      response.Close();
      oFTP = null;

      return true;
    } // DeleteFile()


   }
}

I would also like to give credit to the sites I got large chunks of this code from. Hopefully, if my code doesn't make enough sense, you can use these other sites to help out. This site details uploading a file to an FTP server: http://wiki.asp.net/page.aspx/283/uploading-file-using-ftpwebrequest/.

This site details downloading a file from an FTP server: http://www.eggheadcafe.com/community/aspnet/14/80938/use-ftpwebrequest-to-down.aspx.

This site is what finally helped me figure out SSL, although I don't think their code actually works because it isn't an example but a request for help: http://forums.microsoft.com/MSDN/ShowPost.aspx?PostID=722414&SiteID=1.

Share:
Home
Mobile Site | Full Site
Copyright 2017 © QuinStreet Inc. All Rights Reserved