65.9K
CodeProject 正在变化。 阅读更多。
Home

ASP.NET:在 ASP.NET 项目中使用 SFTP/FTP

2020 年 7 月 20 日

CPOL
viewsIcon

13423

downloadIcon

378

在 ASP.NET 项目中使用 SFTP/FTP

背景

在本文中,我们将检查 FTP/SFTP 在 ASP.NET 项目中的用法。我们将创建一个 FTP/SFTP 客户端类,以连接并对 FTP/SFTP 系统执行操作。

操作包括

  • 连接/断开与服务器的连接
  • 上传/下载文件
  • 检查文件/目录
  • 创建/删除文件/目录
  • 以及其他

SFTP/FTP

以下是一些常见的接口,用于创建 SFTP 和 FTP 客户端的适配器类。

using System;
using System.Collections.Generic;

namespace DotNetFtpSftp
{
    public interface IFileSystem
    {
        bool FileExists(string filePath);
        bool DirectoryExists(string directoryPath);
        void CreateDirectoryIfNotExists(string directoryPath);
        void DeleteFileIfExists(string filePath);
    }

    public interface IRemoteFileSystemContext : IFileSystem, IDisposable 
    {
        bool IsConnected();
        void Connect();
        void Disconnect();

        List<string> FileNames(string directory);
        List<string> FileNames(string directory, string filePrefix, 
                               string fileSuffixOrExtension = "");

        void UploadFile(string localFilePath, string remoteFilePath);
        void DownloadFile(string localFilePath, string remoteFilePath);
    }
}

为了使 SFTP/FTP 正常工作,我们将使用 WinSCP。我们可以将以下代码添加到我们的 packages.config 文件中,或使用 NuGet 进行安装。

<packages>
  <package id="WinSCP" version="5.17.6" targetFramework="net45" />
</packages>

让我们通过实现接口来创建 adapter 类。

using System;
using System.Collections.Generic;
using System.Linq;
using WinSCP;

namespace DotNetFtpSftp
{
    /*winscp example
     * https://winscp.net/eng/docs/library_examples
     * Local Directory:         C:\DumpFiles\file.csv (C:\\DumpFiles\\file.csv)
     * Ftp Directory(WinScp):   /ArchiveFiles/file.csv
     */
    public class FtpSftpFileContext : IRemoteFileSystemContext
    {
        public SessionOptions SessionOptions { get; }

        private Session _session;

        public FtpSftpFileContext(RemoteSystemSetting setting)
        {
            string protocolType = setting.Type;
            SessionOptions = new SessionOptions
            {
                HostName = setting.Host,
                UserName = setting.UserName,
                Password = setting.Password,
                PortNumber = setting.Port,
                Protocol = (Protocol) Enum.Parse(typeof(Protocol), protocolType),
            };
            if (new List<Protocol>(){ Protocol.Sftp }.Contains(SessionOptions.Protocol))
            {
                SessionOptions.GiveUpSecurityAndAcceptAnySshHostKey = true;
            }
        }

        public void Connect()
        {
            _session = new Session();
            _session.Open(SessionOptions);
        }

        public List<string> FileNames(string directory)
        {
            var files = _session.EnumerateRemoteFiles
                        (directory, "", EnumerationOptions.None).ToList();
            return files.Select(x => x.Name).ToList();
        }

        public List<string> FileNames
        (string directory, string filePrefix, string fileSuffixOrExtension = "")
        {
            /*https://winscp.net/eng/docs/file_mask*/
            string mask = filePrefix + "*" + fileSuffixOrExtension;
            var files = _session.EnumerateRemoteFiles
                        (directory, mask, EnumerationOptions.None).ToList();
            return files.Select(x => x.Name).ToList();
        }

        public bool IsConnected()
        {
            var value = _session == null ? false : _session.Opened;
            return value;
        }

        public void Disconnect()
        {
            _session.Close();
        }

        public void UploadFile(string localFilePath, string remoteFilePath)
        {
            TransferOptions transferOptions = new TransferOptions();
            transferOptions.TransferMode = TransferMode.Binary;
            TransferOperationResult transferResult = 
            _session.PutFiles(localFilePath, remoteFilePath, false, transferOptions);
            transferResult.Check();
        }

        public void DownloadFile(string localFilePath, string remoteFilePath)
        {
            TransferOptions transferOptions = new TransferOptions();
            transferOptions.TransferMode = TransferMode.Binary;
            TransferOperationResult transferResult = 
            _session.GetFiles(remoteFilePath, localFilePath, false, transferOptions);
            transferResult.Check();
        }

        public bool FileExists(string filePath)
        {
            bool has = _session.FileExists(filePath);
            return has;
        }

        public bool DirectoryExists(string directoryPath)
        {
            bool has = _session.FileExists(directoryPath);
            return has;
        }

        public void CreateDirectoryIfNotExists(string directoryPath)
        {
            if (!DirectoryExists(directoryPath))
            {
                _session.CreateDirectory(directoryPath);
            }
        }

        public void DeleteFileIfExists(string filePath)
        {
            if (DirectoryExists(filePath))
            {
                _session.RemoveFile(filePath);
            }
        }

        public void Dispose()
        {
            if (_session != null)
            {
                _session.Dispose();
            }
        }
    }
}

Using the Code

以下是 SFTP/FTP 适配器类的用途

RemoteSystemSetting setting = new RemoteSystemSetting()
{
    Type = "Ftp",           /*for sftp use "Sftp" and for ftp use "Ftp"*/
    Host = "xx.xx.xx.xx",   /*host ip*/
    Port = 21,              /*ftp:21, sftp:22*/
    UserName = "xyz",
    Password = "abc"
};

IRemoteFileSystemContext remote = new FtpSftpFileContext(setting);

remote.Connect();                                       /*establish connection*/
remote.DownloadFile("C:\\1.txt", "/test/1.txt");        /*download file*/
remote.UploadFile("C:\\2.txt", "/test/2.txt");          /*upload upload file*/
List<string> files = remote.FileNames("/test/");        /*file names*/
files = remote.FileNames("/test/",  "1", ".txt");       /*search file with prefix, suffix*/

/*others*/
bool value;
value = remote.IsConnected();                           /*check connection done or not*/
value = remote.DirectoryExists("/test/");               /*check if directory exists or not*/
remote.CreateDirectoryIfNotExists("/test/lol/");        /*create directory*/
value = remote.FileExists("/files/test/1.txt");         /*check if file exists or not*/
remote.DeleteFileIfExists("/test/2.txt");               /*delete file*/
remote.Disconnect();                                    /*stop connection*/
remote.Dispose();                                       /*dispose*/

未来工作

即将添加。

/*we don't have, but going to add some*/
/*get all directory name*/
/*download all files*/
/*upload all files*/

关于源代码

这是一个 Visual Studio 2017 解决方案和 .NET Framework 4.5 项目。

  • DotNetFtpSftp:控制台应用程序

该代码对于未经测试的输入可能会抛出意外错误。如果有,请告诉我。

如何对 ASP.NET CORE 执行相同的操作?

历史

  • 2020 年 7 月 20 日:初始版本
© . All rights reserved.