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





5.00/5 (3投票s)
在 ASP.NET CORE 项目中使用 SFTP/FTP
背景
在本文中,我们将检查 FTP/SFTP 在 ASP.NET CORE 项目中的用法。我们将创建一个 FTP/SFTP 客户端类,以连接并对 FTP/SFTP 系统执行操作。
操作包括
- 连接/断开服务器
- 上传/下载文件
- 检查文件/目录
- 创建/删除文件/目录
- 以及其他
Common
以下是一些常见的接口,用于创建 SFTP 和 FTP 客户端的适配器类。
using System;
namespace FileSystem.Core.Remote
{
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();
void SetWorkingDirectory(string path);
void SetRootAsWorkingDirectory();
void UploadFile(string localFilePath, string remoteFilePath);
void DownloadFile(string localFilePath, string remoteFilePath);
string ServerDetails();
}
}
FTP
对于 FTP 工作,我们将使用 FluentFTP。我们可以将以下代码添加到我们的 .csproj 文件中,或使用 NuGet 进行安装。
<ItemGroup>
<PackageReference Include="FluentFTP" Version="19.2.2" />
</ItemGroup>
让我们通过实现接口来创建 adapter
类。
using FluentFTP;
using System;
using System.Collections.Generic;
using System.Net;
using System.Text;
namespace FileSystem.Core.Remote
{
/*FluentFTP example : https://github.com/robinrodricks/FluentFTP
* Local Directory: @"C:\Files\Temp\file.csv"
* @"C:\Files\Temp"
* Ftp Directory(FluentFTP): @"/Files/Temp/file.csv"
* @"/Files/Temp/
*/
public abstract class FtpContext : IRemoteFileSystemContext
{
protected IFtpClient FtpClient { get; set; }
public void Connect()
{
FtpClient.Connect();
}
public void Disconnect()
{
FtpClient.Disconnect();
}
public void Dispose()
{
if (FtpClient != null && !FtpClient.IsDisposed)
{
FtpClient.Dispose();
}
}
/*actions*/
public bool FileExists(string filePath)
{
return FtpClient.FileExists(filePath);
}
public void DeleteFileIfExists(string filePath)
{
if (!FileExists(filePath))
{
FtpClient.DeleteFile(filePath);
}
}
public void UploadFile(string localFilePath, string remoteFilePath)
{
FtpClient.UploadFile(localFilePath, remoteFilePath);
}
public bool DirectoryExists(string directoryPath)
{
return FtpClient.DirectoryExists(directoryPath);
}
public void CreateDirectoryIfNotExists(string directoryPath)
{
if (!DirectoryExists(directoryPath))
{
FtpClient.CreateDirectory(directoryPath);
}
}
public void DownloadFile(string localFilePath, string remoteFilePath)
{
FtpClient.DownloadFile(localFilePath, remoteFilePath);
}
public bool IsConnected()
{
return FtpClient.IsConnected;
}
public void SetWorkingDirectory(string directoryPath)
{
FtpClient.SetWorkingDirectory(directoryPath);
}
public void SetRootAsWorkingDirectory()
{
SetWorkingDirectory("");
}
public abstract string ServerDetails();
}
}
继承 adapter
类,从 setting:RemoteSystemSetting
对象设置连接详细信息。
using FileSystem.Core.Remote;
using FluentFTP;
namespace ConsoleApp.Test
{
class FtpRemoteFileSystem : FtpContext
{
private string _serverDetails;
public FtpRemoteFileSystem(RemoteSystemSetting setting)
{
_serverDetails = FtpHelper.ServerDetails
(setting.Host, setting.Port.ToString(), setting.UserName, setting.Type);
FtpClient = new FtpClient(setting.Host);
FtpClient.Credentials = new System.Net.NetworkCredential
(setting.UserName, setting.Password);
FtpClient.Port = setting.Port;
}
public override string ServerDetails()
{
return _serverDetails;
}
}
}
SFTP
对于 FTP 工作,我们将使用 SSH.NET。我们可以将以下代码添加到我们的 .csproj 文件中,或使用 NuGet 进行安装。
<ItemGroup>
<PackageReference Include="SSH.NET" Version="2016.1.0" />
</ItemGroup>
让我们通过实现接口来创建 adapter
类。
using FluentFTP;
using Renci.SshNet;
using System;
using System.Collections.Generic;
using System.IO;
using System.Net;
using System.Text;
namespace FileSystem.Core.Remote
{
/* SshNet example : https://github.com/sshnet/SSH.NET
* Local Directory: @"C:\Files\Temp\file.csv"
* @"C:\Files\Temp"
* Ftp Directory(FluentFTP): @"/Files/Temp/file.csv"
* @"/Files/Temp/
*/
public abstract class SftpContext : IRemoteFileSystemContext
{
protected SftpClient SftpClient { get; set; }
public void Connect()
{
SftpClient.Connect();
}
public void Disconnect()
{
SftpClient.Disconnect();
}
public void Dispose()
{
if (SftpClient != null)
{
SftpClient.Dispose();
}
}
/*actions*/
public bool FileExists(string filePath)
{
return SftpClient.Exists(filePath);
}
public void DeleteFileIfExists(string filePath)
{
if (!FileExists(filePath))
{
SftpClient.DeleteFile(filePath);
}
}
public void UploadFile(string localFilePath, string remoteFilePath)
{
var fileStream = new FileStream(localFilePath, FileMode.Open);
SftpClient.UploadFile(fileStream, remoteFilePath);
}
public bool DirectoryExists(string directoryPath)
{
return SftpClient.Exists(directoryPath);
}
public void CreateDirectoryIfNotExists(string directoryPath)
{
if (!DirectoryExists(directoryPath))
{
SftpClient.CreateDirectory(directoryPath);
}
}
public void DownloadFile(string localFilePath, string remoteFilePath)
{
using (Stream fileStream = File.Create(localFilePath))
{
SftpClient.DownloadFile(remoteFilePath, fileStream);
}
}
public bool IsConnected()
{
return SftpClient.IsConnected;
}
public void SetWorkingDirectory(string directoryPath)
{
SftpClient.ChangeDirectory(directoryPath);
}
public void SetRootAsWorkingDirectory()
{
SetWorkingDirectory("");
}
public abstract string ServerDetails();
}
}
继承 adapter
类,从 setting:RemoteSystemSetting
对象设置连接详细信息。
using FileSystem.Core.Remote;
using Renci.SshNet;
namespace ConsoleApp.Test
{
public class SftpRemoteFileSystem : SftpContext
{
private string _serverDetails;
public SftpRemoteFileSystem(RemoteSystemSetting setting)
{
_serverDetails = FtpHelper.ServerDetails
(setting.Host, setting.Port.ToString(), setting.UserName, setting.Type);
var connectionInfo = new ConnectionInfo
(setting.Host, setting.Port, setting.UserName,
new PasswordAuthenticationMethod(setting.UserName, setting.Password));
SftpClient = new SftpClient(connectionInfo);
}
public override string ServerDetails()
{
return _serverDetails;
}
}
}
Using the Code
以下是 SFTP/FTP adapter
类的用法
/*Set your SFTP/FTP server details here*/
RemoteSystemSetting setting = new RemoteSystemSetting()
{
Host = "xx.xx.xx.xx", /*host ip*/
Port = 21, /*ftp:21, sftp:22*/
UserName = "xyz",
Password = "abc"
};
IRemoteFileSystemContext remote = new FtpRemoteFileSystem(setting);
/*to use SFTP remote = new SftpRemoteFileSystem(setting);*/
remote.Connect(); /*establish connection*/
remote.SetRootAsWorkingDirectory(); /*set root as work directory*/
remote.DownloadFile("C:\\1.txt", "/files/test/1.txt"); /*download file*/
remote.UploadFile("C:\\2.txt", "/files/test/2.txt"); /*upload upload file*/
/*others*/
bool isConnected = remote.IsConnected(); /*check connection done or not*/
remote.Disconnect(); /*stop connection*/
remote.Dispose(); /*dispose*/
remote.DirectoryExists("/files/test/"); /*check if directory exists or not*/
remote.CreateDirectoryIfNotExists("/files/test/"); /*create directory*/
remote.FileExists("/files/test/1.txt"); /*check if file exists or not*/
remote.DeleteFileIfExists("/files/test/1.txt"); /*delete file*/
remote.SetWorkingDirectory("/files/test"); /*set other directory as root*/
未来工作
即将添加。
/*get all file names*/
/*get all directory names*/
/*download all files*/
/*upload all files*/
其他辅助类
本地文件系统辅助类
此辅助类可用于管理本地路径、目录和文件。
using System.IO;
namespace ConsoleApp.Test
{
public class FileSystemHelper
{
/// <summary>
/// string p1 = "c:\\temp\\";
/// string p2 = "\\subdir\\file\\";
/// to c:\temp\subdir\file
/// </summary>
public static string CombineDirectory
(string rootDirectoryPath, string childDirectoryPath)
{
rootDirectoryPath = rootDirectoryPath.TrimEnd('\\');
childDirectoryPath = childDirectoryPath.Trim('\\');
return Path.Combine(rootDirectoryPath, childDirectoryPath);
}
/// <summary>
/// string p1 = "c:\\temp\\";
/// string p2 = "\\file.text";
/// to c:\temp\file.text
/// </summary>
public static string CombineFile(string rootDirectoryPath, string filePathOrName)
{
rootDirectoryPath = rootDirectoryPath.TrimEnd('\\');
filePathOrName = filePathOrName.Trim('\\');
return Path.Combine(rootDirectoryPath, filePathOrName);
}
public static void CreateDirectoryIfNotExists(string directoryPath)
{
if (!DirectoryExists(directoryPath))
{
Directory.CreateDirectory(directoryPath);
}
}
public static void DeleteFileIfExists(string filePath)
{
if (FileExists(filePath))
{
File.Delete(filePath);
}
}
public static bool DirectoryExists(string directoryPath)
{
return Directory.Exists(directoryPath);
}
public static bool FileExists(string filePath)
{
return File.Exists(filePath);
}
/*file*/
public static void MoveFile(string fromFilePath, string toFilePath)
{
File.Move(fromFilePath, toFilePath);
}
public static void FileAppendAllText(string filePath, string contents)
{
/*create file if doesn't exist and add line*/
File.AppendAllText(filePath, contents);
}
}
}
远程 FTP/SFTP 文件系统辅助类
此辅助类可用于管理 FTP/SFTP 服务器路径、目录和文件。
using System;
namespace ConsoleApp.Test
{
public class FtpHelper
{
/// <summary>
/// string p1 = "/temp";
/// to /temp/
/// </summary>
public static string FtpDirectory(string rootDirectory)
{
rootDirectory = rootDirectory.Trim('/');
return string.Format(@"/{0}/", rootDirectory);
}
/// <summary>
/// string p1 = "/temp/";
/// string p2 = "/subdir/file/";
/// to /temp/subdir/file/
/// </summary>
public static string CombineDirectory(string rootDirectory, string childDirectory)
{
rootDirectory = rootDirectory.Trim('/');
childDirectory = childDirectory.Trim('/');
return string.Format(@"/{0}/{1}/", rootDirectory, childDirectory);
}
/// <summary>
/// string p1 = "/temp/";
/// string p2 = "file.text";
/// to /temp/file.text
/// </summary>
public static string CombineFile(string rootDirectory, string filePathOrName)
{
rootDirectory = rootDirectory.Trim('/'); ;
filePathOrName = filePathOrName.Trim('/'); ;
return string.Format(@"/{0}/{1}", rootDirectory, filePathOrName);
}
public static string ServerDetails
(string host, string port, string userName, string type = "FTP")
{
return String.Format("Type: '{3}' Host:'{0}' Port:'{1}'
User:'{2}'", host, port, userName, type);
}
}
}
本地机器详细信息辅助类
此辅助类可用于获取当前机器的详细信息。
using System;
namespace ConsoleApp.Test
{
public class LocalMachineHelper
{
/*
https://stackoverflow.com/questions/1768198/how-do-i-get-the-computer-name-in-net
https://stackoverflow.com/questions/1233217/
difference-between-systeminformation-computername-environment-machinename-and
*/
public static string ServerDetails()
{
string machineName = String.Empty;
string hostName = String.Empty;
string computerName = String.Empty;
try
{
machineName = Environment.MachineName;
hostName = System.Net.Dns.GetHostName();
computerName = Environment.GetEnvironmentVariable("COMPUTERNAME");
}
catch (Exception ex)
{
}
string details = String.Format("MachineName:'{0}' HostName:'{1}'
ComputerName:'{2}'", machineName, hostName, computerName);
return details;
}
}
}
关于源代码
这是一个 Visual Studio 2017 解决方案和 ASP.NET Core 2.2 项目。
ConsoleApp.Test
:控制台应用程序FileSystem.Core
:SFTP/FTP 代码在这里
该代码对于未经测试的输入可能会抛出意外错误。如果有,请告诉我。
如何在 ASP.NET 中执行相同的操作?
历史
- 2020 年 7 月 14 日:初始版本