本文概述
SFTP代表SSH文件传输协议或安全文件传输协议, 是与SSH打包在一起的独立协议, 在完全安全的连接上以类似的方式工作。尽管SFTP已集成到用户可以使用的许多图形工具中, 但是如果你是开发人员, 则可以将此类功能集成到你的应用程序中。这样, 你可以处理用户使用此工具时的实际操作, 并且他们将继续使用单个应用程序来处理所有事情, 即你的应用程序。
在本文中, 我们将向你展示在WinForms C#中使用广为人知的SSH.NET库使用SFTP时, 如何安装以及如何完成一些基本任务。
1.安装SSH.NET
第一步, 通过NuGET继续在项目中安装SSH.NET库。 SSH.NET是针对.NET的安全Shell(SSH)库, 已针对并行性进行了优化。这个项目的灵感来自从Java移植的Sharp.SSH库, 而且似乎已经有一段时间没有被支持了。该库是使用.NET 4.0进行的完全重写, 没有任何第三方依赖性, 并使用并行性来实现最佳性能。它为同步和异步操作提供SFTP功能, 这正是我们所需要的。
在Visual Studio中打开你的项目, 然后转到窗口右上角的解决方案资源管理器, 然后右键单击项目的解决方案。从上下文菜单中选择”管理NuGet软件包”选项:
从紧急窗口(或选项卡)导航至”浏览”选项卡并搜索SSH.NET。从结果列表中, 选择authro Renci的第一个选项, 然后继续安装:
库安装完成后, 你将可以在项目中使用它而不会出现问题。不要忘了在你的类的顶部(你要使用它的地方)和其他添加SshNet类型:
using Renci.SshNet;
using Renci.SshNet.Sftp;
using System.IO;
2.用法
用法将基本上通过许多示例来显示, 这些示例说明了如何使用SFTP实现所需的最关键的任务:
列出目录中的文件
你可以使用以下使用SFTPClient.ListDirectory方法的代码段(同步)列出目录的内容:
/// <summary>
/// List a remote directory in the console.
/// </summary>
private void listFiles()
{
string host = @"yourSftpServer.com";
string username = "root";
string password = @"p4ssw0rd";
string remoteDirectory = "/some/example/directory";
using (SftpClient sftp = new SftpClient(host, username, password))
{
try
{
sftp.Connect();
var files = sftp.ListDirectory(remoteDirectory);
foreach (var file in files)
{
Console.WriteLine(file.Name);
}
sftp.Disconnect();
}
catch (Exception e)
{
Console.WriteLine("An exception has been caught " + e.ToString());
}
}
}
或通过在另一个线程中运行代码来异步:
Thread myThread = new System.Threading.Thread(delegate () {
string remoteDirectory = "/some/example/directory";
string host = @"yourSftpServer.com";
string username = "root";
string password = @"p4ssw0rd";
using (SftpClient sftp = new SftpClient(host, username, password))
{
try
{
sftp.Connect();
var files = sftp.ListDirectory(remoteDirectory);
foreach (var file in files)
{
Console.WriteLine(file.Name);
}
sftp.Disconnect();
}
catch (Exception er)
{
Console.WriteLine("An exception has been caught " + er.ToString());
}
}
});
myThread.Start();
连接密钥文件和密码
如果你同时使用私钥文件和密码来连接到SFTP服务器, 则可以使用以下代码段创建连接:
string host = @"yourSftpServer.com";
string username = "root";
string password = @"p4ssw0rd";
PrivateKeyFile keyFile = new PrivateKeyFile(@"path/to/OpenSsh-RSA-key.ppk");
var keyFiles = new[] { keyFile };
var methods = new List<AuthenticationMethod>();
methods.Add(new PasswordAuthenticationMethod(username, password));
methods.Add(new PrivateKeyAuthenticationMethod(username, keyFiles));
ConnectionInfo con = new ConnectionInfo(host, 22, username, methods.ToArray());
using (var client = new SftpClient(con))
{
client.Connect();
// Do what you need with the client !
client.Disconnect();
}
下载单个文件
要下载文件, 可以使用SFTPClient.DownloadFile方法, 并使用System.IO.File.OpenWrite方法在本地写入:
/// <summary>
/// Downloads a file in the desktop synchronously
/// </summary>
public void downloadFile()
{
string host = @"yourSftpServer.com";
string username = "root";
string password = @"p4ssw0rd";
// Path to file on SFTP server
string pathRemoteFile = "/var/www/vhosts/some-folder/file_server.txt";
// Path where the file should be saved once downloaded (locally)
string pathLocalFile = Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.Desktop), "download_sftp_file.txt");
using (SftpClient sftp = new SftpClient(host, username, password))
{
try
{
sftp.Connect();
Console.WriteLine("Downloading {0}", pathRemoteFile);
using (Stream fileStream = File.OpenWrite(pathLocalFile))
{
sftp.DownloadFile(pathRemoteFile, fileStream);
}
sftp.Disconnect();
}
catch (Exception er)
{
Console.WriteLine("An exception has been caught " + er.ToString());
}
}
}
或者, 你可以使其异步创建另一个线程并在其中执行代码:
Thread myThread = new System.Threading.Thread(delegate () {
string host = @"yourSftpServer.com";
string username = "root";
string password = @"p4ssw0rd";
// Path to file on SFTP server
string pathRemoteFile = "/var/www/vhosts/some-folder/file_server.txt";
// Path where the file should be saved once downloaded (locally)
string pathLocalFile = Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.Desktop), "download_sftp_file.txt");
using (SftpClient sftp = new SftpClient(host, username, password))
{
try
{
sftp.Connect();
Console.WriteLine("Downloading {0}", pathRemoteFile);
using (Stream fileStream = File.OpenWrite(pathLocalFile))
{
sftp.DownloadFile(pathRemoteFile, fileStream);
}
sftp.Disconnect();
}
catch (Exception er)
{
Console.WriteLine("An exception has been caught " + er.ToString());
}
}
});
myThread.Start();
下载整个目录
如果你需要下载整个目录(甚至是子文件夹和子文件), 则需要创建2个函数, 其中之一是递归的。第一个功能是DownloadFile, 它允许你通过远程目录和本地路径作为参数下载文件。第二个功能是DownloadDirectory方法, 该方法将列出Providen目录中的所有文件并对其进行迭代。分别地, 如果该项是文件, 那么它将使用DownloadFile方法下载它, 或者如果它是一个文件夹, 则它将创建它:
/// <summary>
/// Downloads a remote directory into a local directory
/// </summary>
/// <param name="client"></param>
/// <param name="source"></param>
/// <param name="destination"></param>
private void DownloadDirectory(SftpClient client, string source, string destination, bool recursive = false)
{
// List the files and folders of the directory
var files = client.ListDirectory(source);
// Iterate over them
foreach (SftpFile file in files)
{
// If is a file, download it
if (!file.IsDirectory && !file.IsSymbolicLink)
{
DownloadFile(client, file, destination);
}
// If it's a symbolic link, ignore it
else if (file.IsSymbolicLink)
{
Console.WriteLine("Symbolic link ignored: {0}", file.FullName);
}
// If its a directory, create it locally (and ignore the .. and .=)
//. is the current folder
//.. is the folder above the current folder -the folder that contains the current folder.
else if (file.Name != "." && file.Name != "..")
{
var dir = Directory.CreateDirectory(Path.Combine(destination, file.Name));
// and start downloading it's content recursively :) in case it's required
if (recursive)
{
DownloadDirectory(client, file.FullName, dir.FullName);
}
}
}
}
/// <summary>
/// Downloads a remote file through the client into a local directory
/// </summary>
/// <param name="client"></param>
/// <param name="file"></param>
/// <param name="directory"></param>
private void DownloadFile(SftpClient client, SftpFile file, string directory)
{
Console.WriteLine("Downloading {0}", file.FullName);
using (Stream fileStream = File.OpenWrite(Path.Combine(directory, file.Name)))
{
client.DownloadFile(file.FullName, fileStream);
}
}
接下来, 你可以继续使用凭据创建客户端, 并使用先前创建的方法开始下载远程目录。请注意, 由于下载整个目录会花费一些时间, 因此建议仅以异步方式(创建线程)使用它, 但这只是一个建议, 你可以解开代码:
Thread myThread = new System.Threading.Thread(delegate () {
string host = @"yourSftpServer.com";
string username = "root";
string password = @"p4ssw0rd";
// Path to folder on SFTP server
string pathRemoteDirectory = "/var/www/vhosts/some-folder-to-download";
// Path where the file should be saved once downloaded (locally)
string pathLocalDirectory = Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.Desktop), "example-local-folder");
using (SftpClient sftp = new SftpClient(host, username, password))
{
try
{
sftp.Connect();
// By default, the method doesn't download subdirectories
// therefore you need to indicate that you want their content too
bool recursiveDownload = true;
// Start download of the directory
DownloadDirectory(
sftp, pathRemoteDirectory, pathLocalDirectory, recursiveDownload
);
sftp.Disconnect();
}
catch (Exception er)
{
Console.WriteLine("An exception has been caught " + er.ToString());
}
}
});
myThread.Start();
删除远端档案
要从远程目录中删除文件, 请使用SFTPClient.DeleteFile方法:
/// <summary>
/// Delete a remote file
/// </summary>
private void deleteFile()
{
string host = @"yourSftpServer.com";
string username = "root";
string password = @"p4ssw0rd";
// Path to folder on SFTP server
string pathRemoteFileToDelete = "/var/www/vhosts/folder/somefile.txt";
using (SftpClient sftp = new SftpClient(host, username, password))
{
try
{
sftp.Connect();
// Delete file
sftp.DeleteFile(pathRemoteFileToDelete);
sftp.Disconnect();
}
catch (Exception er)
{
Console.WriteLine("An exception has been caught " + er.ToString());
}
}
}
编码愉快!
评论前必须登录!
注册