Загрузка файлов из SFTP с помощью библиотеки SSH.NET
string host = @"ftphost";
string username = "user";
string password = "********";
string localFileName = System.IO.Path.GetFileName(@"localfilename");
string remoteDirectory = "/export/";
using (var sftp = new SftpClient(host, username, password))
{
sftp.Connect();
var files = sftp.ListDirectory(remoteDirectory);
foreach (var file in files)
{
if (!file.Name.StartsWith("."))
{
string remoteFileName = file.Name;
if (file.LastWriteTime.Date == DateTime.Today)
Console.WriteLine(file.FullName);
File.OpenWrite(localFileName);
string sDir = @"localpath";
Stream file1 = File.OpenRead(remoteDirectory + file.Name);
sftp.DownloadFile(remoteDirectory, file1);
}
}
}
Я использую библиотеку SSH.NET(Renci.SshNet
) для работы с SFTP-сервером. Что мне нужно сделать, так это захватить файлы из определенной папки на SFTP-сервере на основе сегодняшней даты. Затем скопируйте эти файлы с сервера SFTP на локальный диск на моем сервере.
Выше код, который у меня есть, но он не работает. Иногда он говорит, что файл не существует, но иногда файлы, которые я буду загружать, не будут на моих локальных серверах, но мне нужно загрузить все файлы, которые были загружены в удаленную папку на этот день.
Может кто-нибудь взглянуть и посмотреть, что не так? Я считаю, что это как-то связано с частью потока. Я работал с FTP гораздо больше, помимо загрузки файлов, которые я взял с некоторым предыдущим кодом, и думал, что могу изменить процесс, но это не работает. Используемый мной код основан на этом примере.
Ответы
Ответ 1
Простой рабочий код для загрузки файла с помощью библиотеки SSH.NET:
using (Stream fileStream = File.Create(@"C:\target\local\path\file.zip"))
{
sftp.DownloadFile("/source/remote/path/file.zip", fileStream);
}
Чтобы объяснить, почему ваш код не работает:
Второй параметр SftpClient.DownloadFile
- это поток для записи загруженного содержимого в.
Вы передаете поток чтения вместо потока записи. И, кроме того, путь, по которому вы открываете поток чтения, - это удаленный путь, что не может работать с классом File
работающим только с локальными файлами.
Просто File.OpenRead
строку File.OpenRead
и вместо этого используйте результат предыдущего вызова File.OpenWrite
(который вы сейчас не используете):
Stream file1 = File.OpenWrite(localFileName);
sftp.DownloadFile(file.FullName, file1);
Или даже лучше, используйте File.Create
чтобы отменить любое предыдущее содержимое, которое может иметь локальный файл.
Я не уверен, что ваш localFileName
должен содержать полный путь или просто имя файла. Таким образом, вам может понадобиться добавить путь, если необходимо (скомбинировать localFileName
с sDir
?)
Ответ 2
Пока этот пример работает, его не правильный способ обработки потоков...
Вам необходимо обеспечить закрытие файлов/потоков с помощью предложения use. Также добавьте try/catch для обработки ошибок ввода-вывода...
public void DownloadAll()
{
string host = @"sftp.domain.com";
string username = "myusername";
string password = "mypassword";
string remoteDirectory = "/RemotePath/";
string localDirectory = @"C:\LocalDriveFolder\Downloaded\";
using (var sftp = new SftpClient(host, username, password))
{
sftp.Connect();
var files = sftp.ListDirectory(remoteDirectory);
foreach (var file in files)
{
string remoteFileName = file.Name;
if ((!file.Name.StartsWith(".")) && ((file.LastWriteTime.Date == DateTime.Today))
using (Stream file1 = File.OpenWrite(localDirectory + remoteFileName))
{
sftp.DownloadFile(remoteDirectory + remoteFileName, file1);
}
}
}
}
Ответ 3
Моя версия @Merak Marey Code. Я проверяю, существуют ли файлы уже и разные каталоги загрузки для.txt и других файлов
static void DownloadAll()
{
string host = "xxx.xxx.xxx.xxx";
string username = "@@@";
string password = "123";string remoteDirectory = "/IN/";
string finalDir = "";
string localDirectory = @"C:\filesDN\";
string localDirectoryZip = @"C:\filesDN\ZIP\";
using (var sftp = new SftpClient(host, username, password))
{
Console.WriteLine("Connecting to " + host + " as " + username);
sftp.Connect();
Console.WriteLine("Connected!");
var files = sftp.ListDirectory(remoteDirectory);
foreach (var file in files)
{
string remoteFileName = file.Name;
if ((!file.Name.StartsWith(".")) && ((file.LastWriteTime.Date == DateTime.Today)))
{
if (!file.Name.Contains(".TXT"))
{
finalDir = localDirectoryZip;
}
else
{
finalDir = localDirectory;
}
if (File.Exists(finalDir + file.Name))
{
Console.WriteLine("File " + file.Name + " Exists");
}else{
Console.WriteLine("Downloading file: " + file.Name);
using (Stream file1 = File.OpenWrite(finalDir + remoteFileName))
{
sftp.DownloadFile(remoteDirectory + remoteFileName, file1);
}
}
}
}
Console.ReadLine();
}
Ответ 4
Если вы не указали какое-либо конкретное сообщение об ошибке, трудно дать конкретные предложения.
Тем не менее, я использовал тот же пример и получал исключение разрешений в File.OpenWrite - используя переменную localFileName, потому что использование Path.GetFile указывало на местоположение, которое явно не имело бы прав доступа для открытия файла> C:\ProgramFiles\IIS (Express)\filename.doc
Я обнаружил, что использование System.IO.Path.GetFileName неверно, вместо этого используйте System.IO.Path.GetFullPath, укажите на свой файл, начиная с "C:\..."
Также откройте свое решение в FileExplorer и предоставите разрешения asp.net для файла или любых папок, содержащих файл. В этот момент я смог загрузить файл.