2012-02-01 50 views
1

我想上傳文件到FTPS和SFTP。我的代碼目前使用FtpWebRequest對象上傳到FTP。我應該使用哪些更改或類上傳到FTP,FTPS和SFTP服務器?上傳文件到ASP.NET中的安全FTP

+0

你可以使用EnableSSL屬性來做到這一點嗎? – 2012-02-01 16:51:37

+1

[FTP/SFTP模塊的.NET]的可能的重複(http://stackoverflow.com/questions/2731967/ftp-sftp-module-for-net) – 2012-02-01 17:22:54

+0

因此,你沒有做任何功課,沒有做簡單搜索「FTPS SFTP .NET」既不在SO也不在Google。 – 2012-02-01 17:23:39

回答

6

SFTP不是.NET的內置協議,您必須使用第三方庫,如SharpSSH;然而,FTP和FTPS是。有許多商業和開源的第三方庫(SSH Factory for .NETRebex SFTP for .NET/.NET CF,SharpSSH - A Secure Shell (SSH) library for .NET,Compare SFTP (SSH File Transfer Protocol) components for .NET (C#, VB.NET) - SecureBlackbox®),你需要做一些研究來確定哪一個最適合你的需求。

下面是一個示例控制檯應用程序,我寫,做FTP和FTPS使用.NET Framework的的FtpWebRequest:

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

namespace FtpSslTest 
{ 
    class Program 
    { 
     static void Main(string[] args) 
     { 
      string server = null; 

      do 
      { 
       Console.Write("Enter the server to connect to: "); 
       server = Console.ReadLine(); 
      } while (IsServerValid(server) == false); 

      UriBuilder ftpUrl = new UriBuilder("ftp", server); 

      bool useSsl = GetYesNo("Use SSL?"); 
      bool allowInvalidCertificate = false; 
      if (useSsl) 
      { 
       allowInvalidCertificate = GetYesNo("Allow invalid SSL certificate?"); 
      } 

      bool useActiveFtp = GetYesNo("Use Active FTP?"); 

      string path = null; 

      do 
      { 
       Console.Write("Enter the path: "); 
       path = Console.ReadLine(); 
      } while (IsValidPath(path) == false); 

      ftpUrl.Path = path; 

      Console.Write("Enter the user name: "); 
      string userName = Console.ReadLine(); 

      string password = GetPasswordFromUser(); 

      Console.WriteLine(); 
      Console.WriteLine(); 

      List<string> directoryContents = null; 
      try 
      { 
       directoryContents = DisplayDirectoryContents(ftpUrl.ToString(), userName, password, useSsl, allowInvalidCertificate, useActiveFtp, false); 
      } 
      catch (WebException ex) 
      { 
       Console.WriteLine("The request failed with status {0}. {1}", ex.Status, ex.Message); 
      } 
      catch (Exception ex) 
      { 
       Console.Error.WriteLine(ex.ToString()); 
      } 

      if (directoryContents != null && directoryContents.Count == 1) 
      { 
       bool saveFile = GetYesNo(string.Format("Download the file {0} from {1}? ", directoryContents[0], server)); 

       if (saveFile) 
       { 
        string savePath = null; 

        do 
        { 
         Console.Write("Enter a local path to save the file: "); 
         savePath = Console.ReadLine(); 
        } while (!IsValidPath(savePath)); 

        try 
        { 
         DownloadFileFromServer(ftpUrl.ToString(), userName, password, useSsl, allowInvalidCertificate, useActiveFtp, savePath); 
        } 
        catch (WebException ex) 
        { 
         Console.WriteLine("The request failed with status {0}. {1}", ex.Status, ex.Message); 
        } 
        catch (Exception ex) 
        { 
         Console.Error.WriteLine(ex.ToString()); 
        } 
       } 
      } 
     } 

     private static bool GetYesNo(string message) 
     { 
      Console.Write("{0} (Y/N) ", message); 

      string input = null; 

      do 
      { 
       input = new string(Console.ReadKey(true).KeyChar, 1); 
      } while (!input.Equals("Y", StringComparison.CurrentCultureIgnoreCase) && !input.Equals("N", StringComparison.CurrentCultureIgnoreCase)); 

      Console.WriteLine(input); 

      return input.Equals("Y", StringComparison.CurrentCultureIgnoreCase); 
     } 

     private static bool IsValidPath(string path) 
     { 
      bool validPath = false; 

      validPath = path != null && path.IndexOfAny(Path.GetInvalidPathChars()) < 0; 

      if (validPath == false) 
      { 
       Console.WriteLine("You must enter a valid path."); 
      } 

      return validPath; 
     } 

     private static bool IsServerValid(string server) 
     { 
      bool serverValid = false; 

      if (!string.IsNullOrEmpty(server)) 
      { 
       try 
       { 
        IPAddress[] addresses = Dns.GetHostAddresses(server); 
        serverValid = (addresses != null && addresses.Length > 0); 
       } 
       catch (SocketException ex) 
       { 
        Console.WriteLine(ex.Message); 
       } 
      } 
      else 
      { 
       Console.WriteLine("You must provide a valid host name or IP address."); 
      } 

      return serverValid; 
     } 

     private static string GetPasswordFromUser() 
     { 
      Console.Write("Enter the password: "); 
      StringBuilder password = new StringBuilder(); 

      char readChar = '\x00'; 
      while (readChar != '\r') 
      { 
       readChar = Console.ReadKey(true).KeyChar; 

       if (readChar == '\b') 
       { 
        if (password.Length > 0) 
        { 
         password.Length--; 
         Console.Write("\b \b"); 
        } 
       } 
       else if (readChar != '\r') 
       { 
        Console.Write('*'); 
        password.Append(readChar); 
       } 
      } 

      return password.ToString(); 
     } 

     public static bool ServicePointManager_ServerCertificateValidationCallback(object sender, X509Certificate certificate, X509Chain chain, SslPolicyErrors sslPolicyErrors) 
     { 
      bool allowCertificate = true; 

      if (sslPolicyErrors != SslPolicyErrors.None) 
      { 
       Console.WriteLine("Accepting the certificate with errors:"); 
       if ((sslPolicyErrors & SslPolicyErrors.RemoteCertificateNameMismatch) == SslPolicyErrors.RemoteCertificateNameMismatch) 
       { 
        Console.WriteLine("\tThe certificate subject {0} does not match.", certificate.Subject); 
       } 

       if ((sslPolicyErrors & SslPolicyErrors.RemoteCertificateChainErrors) == SslPolicyErrors.RemoteCertificateChainErrors) 
       { 
        Console.WriteLine("\tThe certificate chain has the following errors:"); 
        foreach (X509ChainStatus chainStatus in chain.ChainStatus) 
        { 
         Console.WriteLine("\t\t{0}", chainStatus.StatusInformation); 

         if (chainStatus.Status == X509ChainStatusFlags.Revoked) 
         { 
          allowCertificate = false; 
         } 
        } 
       } 

       if ((sslPolicyErrors & SslPolicyErrors.RemoteCertificateNotAvailable) == SslPolicyErrors.RemoteCertificateNotAvailable) 
       { 
        Console.WriteLine("No certificate available."); 
        allowCertificate = false; 
       } 

       Console.WriteLine(); 
      } 

      return allowCertificate; 
     } 

     private static FtpWebRequest CreateFtpWebRequest(string ftpUrl, string userName, string password, bool useSsl, bool allowInvalidCertificate, bool useActiveFtp) 
     { 
      FtpWebRequest request = (FtpWebRequest)WebRequest.Create(ftpUrl); 
      request.Credentials = new NetworkCredential(userName, password); 

      if (useSsl) 
      { 
       request.EnableSsl = true; 

       if (allowInvalidCertificate) 
       { 
        ServicePointManager.ServerCertificateValidationCallback = ServicePointManager_ServerCertificateValidationCallback; 
       } 
       else 
       { 
        ServicePointManager.ServerCertificateValidationCallback = null; 
       } 
      } 

      request.UsePassive = !useActiveFtp; 

      return request; 
     } 

     private static List<string> DisplayDirectoryContents(string ftpUrl, string userName, string password, bool useSsl, bool allowInvalidCertificate, bool useActiveFtp, bool detailed) 
     { 
      List<string> directoryContents = new List<string>(); 

      FtpWebRequest request = CreateFtpWebRequest(ftpUrl, userName, password, useSsl, allowInvalidCertificate, useActiveFtp); 

      if (detailed) 
      { 
       request.Method = WebRequestMethods.Ftp.ListDirectoryDetails; 
      } 
      else 
      { 
       request.Method = WebRequestMethods.Ftp.ListDirectory; 
      } 

      Stopwatch stopwatch = new Stopwatch(); 
      long bytesReceived = 0; 

      stopwatch.Start(); 
      using (FtpWebResponse response = (FtpWebResponse)request.GetResponse()) 
      { 
       Console.WriteLine(response.BannerMessage); 
       Console.WriteLine(response.WelcomeMessage); 
       Console.WriteLine(response.StatusDescription); 

       using (Stream responseStream = response.GetResponseStream()) 
       using (StreamReader responseStreamReader = new StreamReader(responseStream)) 
       { 
        while (!responseStreamReader.EndOfStream) 
        { 
         string directoryEntry = responseStreamReader.ReadLine(); 
         Console.WriteLine(directoryEntry); 
         directoryContents.Add(directoryEntry); 
        } 
       } 

       Console.WriteLine(response.ExitMessage); 
      } 
      stopwatch.Stop(); 

      Console.WriteLine(); 
      Console.WriteLine("{0} bytes received in {1} seconds.", bytesReceived, stopwatch.ElapsedMilliseconds/1000.0); 

      return directoryContents; 
     } 

     private static List<string> ListDirectoryContents(string ftpUrl, string userName, string password, bool useSsl, bool allowInvalidCertificate, bool useActiveFtp, bool detailed) 
     { 
      List<string> directoryContents = new List<string>(); 

      FtpWebRequest request = CreateFtpWebRequest(ftpUrl, userName, password, useSsl, allowInvalidCertificate, useActiveFtp); 

      if (detailed) 
      { 
       request.Method = WebRequestMethods.Ftp.ListDirectoryDetails; 
      } 
      else 
      { 
       request.Method = WebRequestMethods.Ftp.ListDirectory; 
      } 

      using (FtpWebResponse response = (FtpWebResponse)request.GetResponse()) 
      { 
       using (Stream responseStream = response.GetResponseStream()) 
       using (StreamReader responseStreamReader = new StreamReader(responseStream)) 
       { 
        while (!responseStreamReader.EndOfStream) 
        { 
         string directoryEntry = responseStreamReader.ReadLine(); 
         directoryContents.Add(directoryEntry); 
        } 
       } 

      } 

      return directoryContents; 
     } 

     private static void DownloadFileFromServer(string ftpUrl, string userName, string password, bool useSsl, bool allowInvalidCertificate, bool useActiveFtp, string savePath) 
     { 
      FtpWebRequest request = CreateFtpWebRequest(ftpUrl, userName, password, useSsl, allowInvalidCertificate, useActiveFtp); 

      request.Method = WebRequestMethods.Ftp.DownloadFile; 

      Stopwatch stopwatch = new Stopwatch(); 
      long bytesReceived = 0; 

      stopwatch.Start(); 
      using (FtpWebResponse response = (FtpWebResponse)request.GetResponse()) 
      { 
       Console.WriteLine(response.BannerMessage); 
       Console.WriteLine(response.WelcomeMessage); 
       Console.WriteLine(response.StatusDescription); 

       using (Stream responseStream = response.GetResponseStream()) 
       using (FileStream saveFileStream = File.OpenWrite(savePath)) 
       { 
        // Note that this method call requires .NET 4.0 or higher. If using an earlier version it will need to be replaced. 
        responseStream.CopyTo(saveFileStream); 
       } 

       bytesReceived = response.ContentLength; 
       Console.WriteLine(response.ExitMessage); 
      } 
      stopwatch.Stop(); 

      Console.WriteLine(); 
      Console.WriteLine("{0} bytes received in {1} seconds.", bytesReceived, stopwatch.ElapsedMilliseconds/1000.0); 
     } 

     private static void UploadFileToServer(string ftpUrl, string userName, string password, bool useSsl, bool allowInvalidCertificate, bool useActiveFtp, string filePath) 
     { 
      FtpWebRequest request = CreateFtpWebRequest(ftpUrl, userName, password, useSsl, allowInvalidCertificate, useActiveFtp); 

      request.Method = WebRequestMethods.Ftp.UploadFile; 

      Stopwatch stopwatch = new Stopwatch(); 
      long bytesReceived = 0; 

      stopwatch.Start(); 
      long bytesSent = 0; 
      using (Stream requestStream = request.GetRequestStream()) 
      using (FileStream uploadFileStream = File.OpenRead(filePath)) 
      { 
       // Note that this method call requires .NET 4.0 or higher. If using an earlier version it will need to be replaced. 
       uploadFileStream.CopyTo(requestStream); 
       bytesSent = uploadFileStream.Position; 
      } 

      using (FtpWebResponse response = (FtpWebResponse)request.GetResponse()) 
      { 
       Console.WriteLine(response.BannerMessage); 
       Console.WriteLine(response.WelcomeMessage); 
       Console.WriteLine(response.StatusDescription); 

       bytesReceived = response.ContentLength; 
       Console.WriteLine(response.ExitMessage); 
      } 
      stopwatch.Stop(); 

      Console.WriteLine(); 
      Console.WriteLine("{0} bytes sent in {1} seconds.", bytesSent, stopwatch.ElapsedMilliseconds/1000.0); 
     } 
    } 
} 

您還可以得到詳細的跟蹤調試目的使用帶有示例應用中的配置文件:

<?xml version="1.0"?> 
<configuration> 
    <system.diagnostics> 
    <sources> 
     <source name="System.Net"> 
     <listeners> 
      <add name="TraceFile"/> 
     </listeners> 
     </source> 
     <source name="System.Net.Sockets" maxdatasize="1024"> 
     <listeners> 
      <add name="TraceFile"/> 
     </listeners> 
     </source> 
    </sources> 
    <sharedListeners> 
     <add name="TraceFile" type="System.Diagnostics.TextWriterTraceListener" initializeData="System.Net.trace.log" traceOutputOptions="DateTime"/> 
    </sharedListeners> 
    <switches> 
     <add name="System.Net" value="Verbose"/> 
     <!--<add name="System.Net.Sockets" value="Verbose"/>--> 
    </switches> 
    <trace autoflush="true" /> 
    </system.diagnostics> 
    <startup> 
    <supportedRuntime version="v4.0" sku=".NETFramework,Version=v4.0"/> 
    </startup> 
</configuration> 
2

我用這個庫通過sftp下載和上傳文件。如果您下載源文件,應該是如何使用該庫的示例。 http://sshnet.codeplex.com