web-dev-qa-db-ger.com

Laden Sie Dateien von SFTP mit der SSH.NET-Bibliothek herunter

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);
        }
    }
}

Ich verwende die SSH.NET (Renci.SshNet) -Bibliothek, um mit einem SFTP-Server zu arbeiten. Ich muss Dateien aus einem bestimmten Ordner auf dem SFTP-Server abrufen, basierend auf dem heutigen Datum. Kopieren Sie dann diese Dateien vom SFTP-Server auf einen meiner lokalen Server.

Oben ist der Code, den ich habe, aber er funktioniert nicht. Manchmal heißt es, dass eine Datei nicht existiert, aber manchmal werden sich die Dateien, die ich herunterladen werde, nicht auf meinen lokalen Servern befinden. Ich muss jedoch die Dateien herunterladen, die für diesen Tag in den Remote-Ordner hochgeladen wurden.

Kann jemand einen Blick darauf werfen, was falsch ist? Ich glaube, es hat etwas mit dem Stream-Anteil zu tun. Ich habe viel mit FTP gearbeitet und habe nicht nur Dateien hochgeladen, sondern auch den vorherigen Code, den ich besaß, und dachte, ich könnte den Vorgang rückgängig machen, aber das funktioniert nicht. Der von mir verwendete Code basiert auf diesem Beispiel .

26
user3195153

Ein einfacher Arbeitscode zum Herunterladen einer Datei mit der SSH.NET-Bibliothek lautet:

using (Stream fileStream = File.Create(@"C:\target\local\path\file.Zip"))
{
    sftp.DownloadFile("/source/remote/path/file.Zip", fileStream);
}

Siehe auch Laden eines Verzeichnisses mit SSH.NET SFTP in C # .


Um zu erklären, warum Ihr Code nicht funktioniert:

Der zweite Parameter von SftpClient.DownloadFile ist ein Stream, in den ein heruntergeladener Inhalt geschrieben werden soll.

Sie übergeben einen Lesestrom anstelle eines Schreibstroms. Außerdem ist der Pfad, mit dem Sie den Lesestream öffnen, ein entfernter Pfad, der nicht mit der Klasse File funktioniert, die nur für lokale Dateien ausgeführt wird.

Verwerfen Sie einfach die File.OpenRead-Zeile und verwenden Sie stattdessen ein Ergebnis eines vorherigen File.OpenWrite-Aufrufs (den Sie jetzt überhaupt nicht verwenden):

Stream file1 = File.OpenWrite(localFileName);

sftp.DownloadFile(file.FullName, file1);

Oder noch besser, verwenden Sie File.Create, um alle vorherigen Inhalte der lokalen Datei zu verwerfen.

Ich bin nicht sicher, ob Ihre localFileName den vollständigen Pfad oder nur den Dateinamen enthalten soll. Daher müssen Sie ggf. auch einen Pfad hinzufügen (kombinieren Sie localFileName mit sDir?)

28
Martin Prikryl

Während das Beispiel funktioniert, ist es nicht die richtige Art, mit den Streams umzugehen ...

Sie müssen sicherstellen, dass die Dateien/Streams mit der using - Klausel ...__ geschlossen werden. Fügen Sie außerdem try/catch hinzu, um IO Fehler zu behandeln ...

       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);
                    }
            }

        }
    }
15
Merak Marey

Meine Version von @Merak Mareys Code. Ich überprüfe, ob bereits Dateien vorhanden sind und verschiedene Download-Verzeichnisse für TXT- und andere Dateien

        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();

        }
3
Tasos Mansour

Ohne die Angabe einer bestimmten Fehlermeldung ist es schwierig, konkrete Vorschläge zu machen. 

Ich habe jedoch dasselbe Beispiel verwendet und erhielt eine Ausnahmebedingung für File.OpenWrite - die localFileName -Variable, weil Path.GetFile auf einen Speicherort verweist, der offensichtlich keine Berechtigungen zum Öffnen einer Datei hat. IIS (Express)\Dateiname.doc

Ich habe festgestellt, dass die Verwendung von System.IO.Path.GetFileName nicht korrekt ist. Verwenden Sie stattdessen System.IO.Path.GetFullPath. Zeigen Sie auf Ihre Datei, die mit "C:\..." beginnt.

Öffnen Sie auch Ihre Lösung in FileExplorer und erteilen Sie asp.net Berechtigungen für die Datei oder alle Ordner, die die Datei enthalten. Ich konnte meine Datei zu diesem Zeitpunkt herunterladen.

0
Doug