Downloading a directory using SSH.NET SFTP in C#

18,565

BeginDownloadFile downloads a file. You cannot use it to download a folder. For that you need to download contained files one by one.

The following example uses synchronous download (DownloadFile instead of BeginDownloadFile) for simplicity. After all, you are synchronously waiting for asynchronous download to complete anyway. To implement a progress bar with synchronous download, see Displaying progress of file download in a ProgressBar with SSH.NET.

public static void DownloadDirectory(
    SftpClient sftpClient, string sourceRemotePath, string destLocalPath)
{
    Directory.CreateDirectory(destLocalPath);
    IEnumerable<SftpFile> files = sftpClient.ListDirectory(sourceRemotePath);
    foreach (SftpFile file in files)
    {
        if ((file.Name != ".") && (file.Name != ".."))
        {
            string sourceFilePath = sourceRemotePath + "/" + file.Name;
            string destFilePath = Path.Combine(destLocalPath, file.Name);
            if (file.IsDirectory)
            {
                DownloadDirectory(sftpClient, sourceFilePath, destFilePath);
            }
            else
            {
                using (Stream fileStream = File.Create(destFilePath))
                {
                    sftpClient.DownloadFile(sourceFilePath, fileStream);
                }
            }
        }
    }
}
Share:
18,565

Related videos on Youtube

BandaidMan
Author by

BandaidMan

Updated on September 15, 2022

Comments

  • BandaidMan
    BandaidMan over 1 year

    I am using Renci.SSH and C# to connect to my Unix server from a Windows machine. My code works as expected when the directory contents are only files, but if the directory contains a folder, I get this

    Renci.SshNet.Common.SshException: 'Failure'

    This is my code, how can I update this to also download a directory (if exists)

    private static void DownloadFile(string arc, string username, string password)
    {
        string fullpath;
        string fp;
        var options = new ProgressBarOptions
        {
            ProgressCharacter = '.',
            ProgressBarOnBottom = true
        };
    
        using (var sftp = new SftpClient(Host, username, password))
        {
            sftp.Connect();
            fp = RemoteDir + "/" + arc;
            if (sftp.Exists(fp))     
                fullpath = fp;
            else
                fullpath = SecondaryRemoteDir + d + "/" + arc;
    
            if (sftp.Exists(fullpath))
            {
                var files = sftp.ListDirectory(fullpath);
                foreach (var file in files)
                {
                    if (file.Name.ToLower().Substring(0, 1) != ".")
                    {
                        Console.WriteLine("Downloading file from the server...");
                        Console.WriteLine();
                        using (var pbar = new ProgressBar(100, "Downloading " + file.Name + "....", options))
                        {
                            SftpFileAttributes att = sftp.GetAttributes(fullpath + "/" + file.Name);
                            var fileSize = att.Size;
                            var ms = new MemoryStream();
                            IAsyncResult asyncr = sftp.BeginDownloadFile(fullpath + "/" + file.Name, ms);
                            SftpDownloadAsyncResult sftpAsyncr = (SftpDownloadAsyncResult)asyncr;
                            int lastpct = 0;
                            while (!sftpAsyncr.IsCompleted)
                            {
                                int pct = (int)((long)sftpAsyncr.DownloadedBytes / fileSize) * 100;
                                if (pct > lastpct)
                                    for (int i = 1; i < pct - lastpct; i++)
                                        pbar.Tick();
                            }
                            sftp.EndDownloadFile(asyncr);
                            Console.WriteLine("Writing File to disk...");
                            Console.WriteLine();
                            string localFilePath = "C:\" + file.Name;
                            var fs = new FileStream(localFilePath, FileMode.Create, FileAccess.Write);
                            ms.WriteTo(fs);
                            fs.Close();
                            ms.Close();
                        }
                    }
                }
            }
            else
            {
                Console.WriteLine("The arc " + arc + " does not exist");
                Console.WriteLine();
                Console.WriteLine("Please press any key to close this window");
                Console.ReadKey();
            }
        }
    }