Как получить доступ к SFTP-серверу, используя SSH.NET (синхронизация и асинхронность) с C # в WinForms

SFTP расшифровывается как SSH File Transfer Protocol или Secure File Transfer Protocol, это отдельный протокол, упакованный с SSH, который работает аналогичным образом по полностью защищенному соединению. Хотя SFTP интегрирован во многие графические инструменты, которые могут использовать ваши пользователи, если вы разработчик, вы можете интегрировать такую ​​функцию в свое приложение. Таким образом, вы можете справиться с тем, что на самом деле делают пользователи, когда работают с этим инструментом, и они будут продолжать использовать одно приложение для всего, а именно для вас.

В этой статье мы покажем вам, как установить и как выполнить некоторые типичные обязанности при работе с SFTP в WinForms C # с использованием широко известной библиотеки SSH.NET.

1. Установите SSH.NET

В качестве первого шага приступите к установке библиотеки SSH.NET в своем проекте через NuGET. SSH.NET — это библиотека Secure Shell (SSH) для .NET, оптимизированная для параллелизма. Этот проект был вдохновлен библиотекой Sharp.SSH, которая была портирована из Java, и, кажется, не поддерживалась в течение достаточно долгого времени. Эта библиотека полностью переписана с использованием .NET 4.0, без каких-либо сторонних зависимостей, с использованием параллелизма для достижения максимальной производительности. Он обеспечивает функциональность SFTP как для синхронных, так и для асинхронных операций, это именно то, что нам нужно.

Откройте свой проект в Visual Studio и перейдите в обозреватель решений в верхней правой части окна и щелкните правой кнопкой мыши решение вашего проекта. В контекстном меню выберите Управление пакетами NuGet опция:

Установите SSH.NET с помощью NuGet

В появившемся окне (или вкладке) перейдите на вкладку «Обзор» и найдите SSH.NET. Из списка результатов выберите первый вариант от автора Renci и перейдите к установке:

Установите SSH.NET из репозитория nuGet от renci

После завершения установки библиотеки вы сможете без проблем использовать ее в своем проекте. Не забудьте включить тип SshNet вверху вашего класса (где вы хотите его использовать) и другие:

using Renci.SshNet;
using Renci.SshNet.Sftp;
using System.IO;

2. Использование

Использование будет показано в основном с множеством примеров того, как вы можете решить наиболее типичные задачи, которые вам нужно выполнить с SFTP:

Список файлов из каталога

Вы можете перечислить содержимое каталога, используя следующий фрагмент (синхронно), который использует SFTPClient.ListDirectory метод:

///
/// List a remote directory in the console.
///
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();
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 метод:

///
/// Downloads a file in the desktop synchronously
///
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, который перечисляет все файлы в каталоге provn и перебирает их. Соответственно, если элемент является файлом, он будет использовать метод DownloadFile для его загрузки или, если это папка, он создаст его:

///
/// Downloads a remote directory into a local directory
///
///
///
///
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);
}
}
}
}
///
/// Downloads a remote file through the client into a local directory
///
///
///
///
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 метод:

///
/// Delete a remote file
///
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());
}
}
}
Ссылка на основную публикацию
Adblock
detector