Francis
Francis

Reputation: 343

Upload whole folder with SSH.NET

I use SSH.NET in C# 2015.

With this method I can upload a file to my SFTP server.

public void upload()
{
    const int port = 22;
    const string host = "*****";
    const string username = "*****";
    const string password = "*****";
    const string workingdirectory = "*****";
    string uploadfolder = @"C:\test\file.txt";

    Console.WriteLine("Creating client and connecting");
    using (var client = new SftpClient(host, port, username, password))
    {
        client.Connect();
        Console.WriteLine("Connected to {0}", host);

        client.ChangeDirectory(workingdirectory);
        Console.WriteLine("Changed directory to {0}", workingdirectory);

        using (var fileStream = new FileStream(uploadfolder, FileMode.Open))
        {
            Console.WriteLine("Uploading {0} ({1:N0} bytes)",
                                uploadfolder, fileStream.Length);
            client.BufferSize = 4 * 1024; // bypass Payload error large files
            client.UploadFile(fileStream, Path.GetFileName(uploadfolder));
        }
    }
}

Which works perfectly for a single file. Now I want to upload a whole folder/directory.

Does anybody now how to achieve this?

Upvotes: 13

Views: 10818

Answers (3)

user890332
user890332

Reputation: 1361

I would do like @martin_prikryl above, except I would add to the top of the function the following code so that directories could be created if not exist:

string path=string.Empty;
foreach(var p in remotePath.Split('/'))
{
    path += "/" + p;
    if (!client.Exists(path))
    {
        client.CreateDirectory(path);
    }
}

Upvotes: -1

Martin Prikryl
Martin Prikryl

Reputation: 202088

There's no magical way. You have to enumerate the files and upload them one-by-one:

void UploadDirectory(SftpClient client, string localPath, string remotePath)
{
    Console.WriteLine("Uploading directory {0} to {1}", localPath, remotePath);

    IEnumerable<FileSystemInfo> infos =
        new DirectoryInfo(localPath).EnumerateFileSystemInfos();
    foreach (FileSystemInfo info in infos)
    {
        if (info.Attributes.HasFlag(FileAttributes.Directory))
        {
            string subPath = remotePath + "/" + info.Name;
            if (!client.Exists(subPath))
            {
                client.CreateDirectory(subPath);
            }
            UploadDirectory(client, info.FullName, remotePath + "/" + info.Name);
        }
        else
        {
            using (var fileStream = new FileStream(info.FullName, FileMode.Open))
            {
                Console.WriteLine(
                    "Uploading {0} ({1:N0} bytes)",
                    info.FullName, ((FileInfo)info).Length);

                client.UploadFile(fileStream, remotePath + "/" + info.Name);
            }
        }
    }
}

If you want a simpler code, you will have to use another library. For example my WinSCP .NET assembly can upload whole directory using a single call to Session.PutFilesToDirectory:

var results = session.PutFilesToDirectory(localPath, remotePath);
results.Check();

Upvotes: 17

Marco
Marco

Reputation: 1

If it helps, I have translated the code into VB.NET:

Sub UploadDirectorySftp(Client As SftpClient, LocalPath As String, RemotePath As String)

    Dim subPath As String
    Dim Infos As IEnumerable(Of FileSystemInfo) =
        New DirectoryInfo(LocalPath).EnumerateFileSystemInfos()
    For Each info In Infos
        If info.Attributes.HasFlag(FileAttributes.Directory) Then
            subPath = RemotePath + "/" + info.Name
            If Not Client.Exists(subPath) Then
                Client.CreateDirectory(subPath)
            End If
            UploadDirectorySftp(Client, info.FullName, RemotePath + "/" + info.Name)
        Else
            Using filestream = New FileStream(info.FullName, FileMode.Open)
                Client.UploadFile(filestream, RemotePath + "/" + info.Name)
            End Using
        End If
    Next

End Sub

Example of use:

Using ServerClient = New Renci.SshNet.SftpClient("host", porta, "user", "pswd")
    ServerClient.Connect()
    UploadDirectorySftp(ServerClient, "V:\aaa\", "Immagini")
    ServerClient.Disconnect()
End Using

Upvotes: -4

Related Questions