Загрузка файлов из 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 для файла или любых папок, содержащих файл. В этот момент я смог загрузить файл.