web-dev-qa-db-fra.com

Télécharger des fichiers à partir de SFTP avec la bibliothèque 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);
        }
    }
}

J'utilise la bibliothèque SSH.NET (Renci.SshNet) pour travailler avec un serveur SFTP. Ce que je dois faire, c'est récupérer les fichiers d'un dossier spécifique sur le serveur SFTP en fonction de la date du jour. Copiez ensuite ces fichiers du serveur SFTP sur un lecteur local, un de mes serveurs.

Ci-dessus est le code que j'ai mais il ne fonctionne pas. Parfois, cela signifie que le fichier n'existe pas mais que les fichiers que je téléchargerai ne se trouveront pas sur mes serveurs locaux, mais je dois télécharger tous les fichiers téléchargés dans le dossier distant pour la journée.

Quelqu'un peut-il jeter un coup d'œil et voir ce qui ne va pas? Je crois que cela a quelque chose à voir avec la partie stream. En plus de télécharger des fichiers, j’ai travaillé avec FTP, mais j’avais pris le code que j’avais précédemment et je pensais pouvoir inverser le processus, mais cela ne fonctionnait pas. Le code que j'ai utilisé est basé sur cet exemple .

26
user3195153

Un code de travail simple pour télécharger un fichier avec la bibliothèque SSH.NET est:

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

Voir aussi Téléchargement d'un répertoire avec SSH.NET SFTP en C # .


Pour expliquer, pourquoi votre code ne fonctionne pas:

Le deuxième paramètre de SftpClient.DownloadFile est un flux dans lequel écrire un contenu téléchargé.

Vous transmettez un flux de lecture au lieu d'un flux d'écriture. De plus, le chemin avec lequel vous ouvrez le flux de lecture est un chemin distant, ce qui ne peut fonctionner avec la classe File fonctionnant uniquement sur des fichiers locaux.

Supprime simplement la ligne File.OpenRead et utilise à la place le résultat de l'appel File.OpenWrite précédent (que vous n'utilisez plus du tout):

Stream file1 = File.OpenWrite(localFileName);

sftp.DownloadFile(file.FullName, file1);

Ou encore mieux, utilisez File.Create pour supprimer tout contenu précédent que le fichier local pourrait avoir.

Je ne sais pas si votre localFileName est supposée contenir un chemin complet, ou juste un nom de fichier. Il se peut donc que vous deviez également ajouter un chemin, si nécessaire (combinez localFileName avec sDir?)

28
Martin Prikryl

Bien que l'exemple fonctionne, ce n'est pas la bonne façon de gérer les flux ...

Vous devez vous assurer de la fermeture des fichiers/flux avec la clause using ... ... et ajouter/try pour gérer les erreurs IO.

       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

Ma version du code de @Merak Marey. Je vérifie si des fichiers existent déjà et des répertoires de téléchargement différents pour les fichiers .txt et autres.

        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

Sans message d'erreur spécifique, il est difficile de faire des suggestions spécifiques. 

Cependant, j’utilisais le même exemple et obtenais une exception d’autorisations sur File.OpenWrite - en utilisant la variable localFileName, car en utilisant Path.GetFile pointait sur un emplacement qui, de toute évidence, ne serait pas autorisé à ouvrir un fichier> C:\ProgramFiles\IIS (Express)\nom_fichier.doc

J'ai constaté que l'utilisation de System.IO.Path.GetFileName n'est pas correcte. Utilisez plutôt System.IO.Path.GetFullPath, pointez sur votre fichier commençant par "C:\...".

Ouvrez également votre solution dans FileExplorer et accordez des autorisations à asp.net pour le fichier ou tout dossier contenant le fichier. J'ai pu télécharger mon fichier à ce moment-là.

0
Doug