22

I know that I can upload and download files from/to a SFTP server using SftpClient class of SSH.NET library but I am not sure how can this class be used for copying or moving a remote file on the SFTP server. I also did not find relevant material on internet. How can i copy or move a remote file from directory A to directory B, using SSH.NET library and C#.

Update: I also tried experimenting with SshClient class using the below code but it does nothing, neither any error nor any exception.

ConnectionInfo ConnNfo = new ConnectionInfo("FTPHost", 22, "FTPUser",
new AuthenticationMethod[]{

   // Pasword based Authentication
   new PasswordAuthenticationMethod("FTPUser","FTPPass")
   }                
   );

using (var ssh = new SshClient(ConnNfo))
{
    ssh.Connect();                
    if (ssh.IsConnected)
    {                    
         string comm = "pwd";
         using (var cmd = ssh.CreateCommand(comm))
         {
            var returned = cmd.Execute();
            var output = cmd.Result;
            var err = cmd.Error;
            var stat = cmd.ExitStatus;
         }
     }
   ssh.Disconnect();
}

On Visual Studio console, i get the below output.

*SshNet.Logging Verbose: 1 : SendMessage to server 'ChannelRequestMessage': 'SSH_MSG_CHANNEL_REQUEST : #152199'.

SshNet.Logging Verbose: 1 : ReceiveMessage from server: 'ChannelFailureMessage': 'SSH_MSG_CHANNEL_FAILURE : #0'.*

4
  • are you able to telnet the ftp server in cmd? Commented Dec 11, 2015 at 6:20
  • I can successfully connect and copy paste files using WinSCP utility. Apart from that, I can successfully connect and download files using the 'SftpClient' class of SSH.NET library. Commented Dec 11, 2015 at 11:13
  • How about if you use RunCommand instead of CreateCommand? Commented Dec 14, 2015 at 5:32
  • This link might be useful: stackoverflow.com/questions/11169396/… Commented Dec 14, 2015 at 5:33

3 Answers 3

23

With the NuGet package SSH.NET by Renci I use the following:

using Renci.SshNet;
using Renci.SshNet.SftpClient;    

...

        SftpClient _sftp = new SftpClient(_host, _username, _password);

To Move a file:

        var inFile = _sftp.Get(inPath);
        inFile.MoveTo(outPath);

To Copy a file:

       var fsIn = _sftp.OpenRead(inPath);
       var fsOut = _sftp.OpenWrite(outPath);

        int data;
        while ((data = fsIn.ReadByte()) != -1)
            fsOut.WriteByte((byte)data);

        fsOut.Flush();
        fsIn.Close();
        fsOut.Close();
Sign up to request clarification or add additional context in comments.

6 Comments

This is by far the easiest and best solution here, its also the only solution that worked for me.
Was there a reason you didn't flush fsIn?
I think the fsOut.Flush() essentially forced an fsIn.Flush() but not 100% sure
note that MoveTo will move all the files to the new directory
I think it must be Open(outPath, FileMode.Create, FileAccess.Write); instead of OpenWrite(outPath). Because OpenWrite not overwrite file. github.com/sshnet/SSH.NET/blob/…
|
20

In addition to SSH.NET's SftpClient, there is also the simpler ScpClient which worked when I ran into SftpClient issues. ScpClient only has upload/download functionality, but that satisfied my use case.

Uploading:

using (ScpClient client = new ScpClient(host, username, password))
{
    client.Connect();

    using (Stream localFile = File.OpenRead(localFilePath))
    {
         client.Upload(localFile, remoteFilePath);
    }
}

Downloading:

using (ScpClient client = new ScpClient(host, username, password))
{
    client.Connect();

    using (Stream localFile = File.Create(localFilePath))
    {
         client.Download(remoteFilePath, localFile);
    }
}

2 Comments

Works. Make sure to include the SSH.NET in your project. I used the Nuget package manager.
Is it possible to have any info about progress of uploading?
16

Moving a remote File can be done using SSH.NET library. Available here: https://github.com/sshnet/SSH.NET

Here is sample code to move first file from one source folder to another. Set private variables in the class according to the FTP set up.

using System;
using System.Linq;
using System.Collections.Generic;
using Renci.SshNet;
using Renci.SshNet.Sftp;
using System.IO;
using System.Configuration;
using System.IO.Compression;

public class RemoteFileOperations
{
    private string ftpPathSrcFolder = "/Path/Source/";//path should end with /
    private string ftpPathDestFolder = "/Path/Archive/";//path should end with /
    private string ftpServerIP = "Target IP";
    private int ftpPortNumber = 80;//change to appropriate port number
    private string ftpUserID = "FTP USer Name";//
    private string ftpPassword = "FTP Password";
    /// <summary>
    /// Move first file from one source folder to another. 
    /// Note: Modify code and add a for loop to move all files of the folder
    /// </summary>
    public void MoveFolderToArchive()
    {
        using (SftpClient sftp = new SftpClient(ftpServerIP, ftpPortNumber, ftpUserID, ftpPassword))
        {
            SftpFile eachRemoteFile = sftp.ListDirectory(ftpPathSrcFolder).First();//Get first file in the Directory            
            if(eachRemoteFile.IsRegularFile)//Move only file
            {
                bool eachFileExistsInArchive = CheckIfRemoteFileExists(sftp, ftpPathDestFolder, eachRemoteFile.Name);

                //MoveTo will result in error if filename alredy exists in the target folder. Prevent that error by cheking if File name exists
                string eachFileNameInArchive = eachRemoteFile.Name;

                if (eachFileExistsInArchive)
                {
                    eachFileNameInArchive = eachFileNameInArchive + "_" + DateTime.Now.ToString("MMddyyyy_HHmmss");//Change file name if the file already exists
                }
                eachRemoteFile.MoveTo(ftpPathDestFolder + eachFileNameInArchive);
            }           
        }
    }

    /// <summary>
    /// Checks if Remote folder contains the given file name
    /// </summary>
    public bool CheckIfRemoteFileExists(SftpClient sftpClient, string remoteFolderName, string remotefileName)
    {
        bool isFileExists = sftpClient
                            .ListDirectory(remoteFolderName)
                            .Any(
                                    f => f.IsRegularFile &&
                                    f.Name.ToLower() == remotefileName.ToLower()
                                );
        return isFileExists;
    }

}

1 Comment

Thanks for the suggestion about checking if the file already exists before moving it. I was getting a general Failure error, but in reality it was caused by this issue.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.