Click here to Skip to main content
65,938 articles
CodeProject is changing. Read more.
Articles
(untagged)

sFTP and .NET

0.00/5 (No votes)
6 May 2014 2  
How to achieve sFTP using .NET

Introduction

With the release of the new .NET 4.5 framework; I was pretty stoked at diving in and seeing all the new functionality available. One of the most talked about features was the improvements to the Asynchronous Programming model (previous versions used TPL). This is great, and will get used a lot by developers. But, one of the features I (and few others) were looking for was the support for sFTP built-in the .NET framework. Sadly, it was not found.

After some rigorous searching for a .NET wrapper to handle secure shell transmissions, I came across WinSCP; which is not only free (the best part!), but also included a wrapper to use in code. Jackpot!

Using WinSCP is really straightforward. The developer has done an excellent job in documenting, an active community of users, and really just putting together a tool that interfaces well with .NET.

Background

Some knowledge might be helpful on how currently .NET handles FTP and a quick read on FtpWebRequest and FtpWebResponse would be helpful, but not necessary.

Remember, there are a number of ways to transfer files using FTP and sFTP. But this particular scenario needed to transfer files via code (C#). Oh, and as an aside, the 's' in front of 'sFTP' does not mean 'secure' (literally), but instead stands for 'SSH' - secure shell.

Another note, in order to use WinSCP, you will need the SSHHostKeyFingerprint for the designated server you are trying to connect to. If you are not sure about how to obtain this, you can always ask your administrator for this key. This key is not top secret information and should be available to you publicly.

Or, similarly, you could install a FTP client that also handles SSH transmissions and grab the SSH Host Key Fingerprint via the options menu for the tools that have been tested below:

For WS_FTP:

  1. Download and install WS_FTP (trial version will work as well).
  2. Connect to your sFTP site via the hostname, username, and password.
  3. When prompted to examine the "Untrusted SSH Host Key", select "Trust this key"
  4. If you ever need to recover the SSH Host Key, you can go to Tools -> Options -> SSH (On the left) -> Trusted Hosts

For WinSCP:

  1. Download and install WinSCP.
  2. Connect to your sFTP site using your hostname, username, and password.
  3. Once connected, you can retrieve the SSH host key fingerprint by going into "Commands" -> "Server/Protocol Information". You should see the SSH Host Key Fingerprint in the "Protocol" tab.

For FileZilla:

  1. Download and install Filezilla.
  2. Connect to your sFTP using your hostname, username, and password
  3. Once you're connected, you'll be prompted to accept the SSH Host Key. At this point, I would get a screen shot of the SSH Host Key or write it down. Once you get past the SSH Key pop-up and haven't copied this key, it's going to be a challenge to get that key out of FileZilla. This is because FileZilla uses a adapted PuTTY component for sFTP support. FileZilla and PuTTY share the host key cache.
  4. Here's a way to get the host key out of FileZilla (it's long and involves the registry).

If you get 'click happy', you're likely to miss the dialog and will probably need to re-install FileZilla (with some registry magic) to review the key again. So, read the prompts that you're being asked to click through :-).

That was longer than intended...now charge forward...

Using the Code

Now the best part! Go here to grab the WinSCP assembly. We're assuming that you are well versed in Visual Studio project files and how to add, remove, compile, and build projects.

There will be two files in the .NET assembly WinSCP download. One will be the actual assembly itself (WinSCPnet.dll) and the second file will be the executable, WinSCP.exe.

Add both of these files to your Visual Studio project output folder; which should be the /obj/debug folder. For simplicity sake, the files WinSCPnet.dll and WinSCp.exe should be copied into the output folder for this scenario. If you want to use a different folder, then you can set the "Session.ExecutablePath" property of the WinSCP API to tell the assembly to look in a different folder other than the output path. A more detailed instruction list is available here at the WinSCP site.

In our scenario, we were going to be doing two functions:

  1. Get the files off of a sFTP site, or
  2. Put the files on an sFTP site.

The code is going be really similar for both of these actions.

Get Files (pull down from sFTP - Download)

using WinSCP; //Namespace 
...
//Get Files - ideally you would want to wrap this into a try...catch 
//and possible execute more than once if you can't connect the first time. 
SessionOptions sessionOptions = new SessionOptions
{
    Protocol = Protocol.Sftp,
    HostName = ftpServerName, //hostname e.g. IP: 192.54.23.32, or mysftpsite.com
    UserName = ftpUser,
    Password = ftpPwd, 
    PortNumber = 22,
    SshHostKeyFingerprint = "ssh - rsa //followed by your 16 bit key" 
};
using (Session session = new Session())
{
    session.SessionLogPath = "your log path";
    Session.Open(sessionOptions); //Attempts to connect to your sFtp site
    //Get Ftp File
    TransferOptions transferOptions = new TransferOptions(); 
    transferOptions.TransferMode = TransferMode.Binary; //The Transfer Mode - Automatic, Binary, or Ascii 
    transferOptions.FilePermissions = null;  //Permissions applied to remote files; 
    //<em style="font-size: 9pt;">null for default permissions.  
    //Can set <em style="font-size: 9pt;">user, Group, or other Read/Write/Execute permissions.  
    transferOptions.PreserveTimestamp = false;  //Set last write time of destination file 
    //to that of source file - basically change the timestamp to match destination and source files.    
    transferOptions.ResmeSupport.State = TransferResumeSupportState.Off;
     
     TransferOperationalResult transferResult;
    //the parameter list is: remote Path, Local Path with filename 
    //(optional - if different from remote path), Delete source file?, transfer Options  
    transferResult = session.GetFiles("/" + filenameToGet, PathToPlaceFile, false, transferOptions; 
    //Throw on any error 
    transferResult.Check()  
    //Log information and break out if necessary  
} 

Put Files (Send FTP Files - Upload)

using WinSCP; //Namespace 
...
//Send Ftp Files - same idea as above - try...catch and try to repeat this code 
//if you can't connect the first time, timeout after a certain number of tries. 
SessionOptions sessionOptions = new SessionOptions
{
    Protocol = Protocol.Sftp,
    HostName = ftpServerName, //hostname e.g. IP: 192.54.23.32, or mysftpsite.com
    UserName = ftpUser,
    Password = ftpPwd, 
    PortNumber = 22,
    SshHostKeyFingerprint = "ssh - rsa //followed by your 16 bit key" 
};
using (Session session = new Session())
{
    session.SessionLogPath = "your log path";
    Session.Open(sessionOptions); //Attempts to connect to your sFtp site
    //Get Ftp File
    TransferOptions transferOptions = new TransferOptions(); 
    transferOptions.TransferMode = TransferMode.Binary; //The Transfer Mode - 
    //<em style="font-size: 9pt;">Automatic, Binary, or Ascii  
    transferOptions.FilePermissions = null; //Permissions applied to remote files; 
    //null for default permissions.  Can set user, 
    //Group, or other Read/Write/Execute permissions. 
    transferOptions.PreserveTimestamp = false; //Set last write time of 
    //destination file to that of source file - basically change the timestamp 
    //to match destination and source files.   
    transferOptions.ResmeSupport.State = TransferResumeSupportState.Off;
     
     TransferOperationalResult transferResult;
    //the parameter list is: local Path, Remote Path, Delete source file?, transfer Options  
    transferResult = session.PutFiles(localPathWithFilename, RemotePath, false, transferOptions; 
    //Throw on any error 
    transferResult.Check() 
    //Log information and break out if necessary  
} 

The WinSCP site has GREAT documentation on all the methods covered above and examples (C# and VB.NET) can be found here. The attempt here is to make it all concise and just get the sFTP transfer working quickly.

Points of Interest

Do keep in mind that sFTP is not the same as FTPS. sFTP is 'secure shell' and FTPs is SSL over FTP - totally two different concepts. A simple search will get you tons of information.

The WinSCP .NET wrapper has been nothing short of a life saver. There are other solutions out there (Granados, SharpSSH, etc.) and find one that works for you. Here is a discussion on sFTP libraries that you could use from stackoverflow.com.

Hope that this helps and corrections are welcome!

History

  • 6th May, 2014: Initial version

License

This article has no explicit license attached to it but may contain usage terms in the article text or the download files themselves. If in doubt please contact the author via the discussion board below.

A list of licenses authors might use can be found here