将文件上载到ASP.NET中的安全FTP

时间:2012-02-01 16:48:27

标签: asp.net ftp sftp ftps

我想将文件上传到FTPS和SFTP。我的代码目前正在使用FtpWebRequest对象上传到FTP。我应该使用哪些更改或类来上传到FTP,FTPS和SFTP服务器?

2 个答案:

答案 0 :(得分:6)

SFTP不是.NET的内置协议,你必须使用像SharpSSH这样的第三方库;但是,FTP和FTPS都是。商业和OpenSource(SSH Factory for .NET Rebex SFTP for .NET/.NET CFSharpSSH - A Secure Shell (SSH) library for .NETCompare SFTP (SSH File Transfer Protocol) components for .NET (C#, VB.NET) - SecureBlackbox®都有许多第三方库,您需要做一些研究来确定哪个一个最适合你的需求。

这是我编写的一个示例控制台应用程序,它使用.NET Framework的FtpWebRequest执行FTP和FTPS:

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>

答案 1 :(得分:2)

我使用此库通过sftp下载和上传文件。如果您下载源代码,应该是如何使用库的示例。 http://sshnet.codeplex.com