Achieving FTP/SFTP without 3rd party dll with FtpWebRequest if possible in C#
.net, c#, winforms
Solution
UPDATE:
If using BizTalk, you can work with the SFTP Adapter, using the ESB Toolkit. It has been supported since 2010. One wonders why it didn't make it to the `.Net Framework`
- BizTalk Server 2013: Creating Custom Adapter Provider in ESB Toolkit SFTP As an Example
- BizTalk Server 2013: How to use SFTP Adapter
- MSDN Docs
--
Unfortunately, it still requires alot of work to do with just the Framework currently. Placing the `sftp` protocol prefix isnt enough to `make-it-work` Still no built-in, .Net Framework support today, maybe in the future.
---------------------------------------------------------
1) A good library to try out is SSHNet.
---------------------------------------------------------
It has:
- a lot more features, including built-in streaming support.
- an API document
- a simpler API to code against
Example code from documentation:
List directory
/// <summary>
/// This sample will list the contents of the current directory.
/// </summary>
public void ListDirectory()
{
string host = "";
string username = "";
string password = "";
string remoteDirectory = "."; // . always refers to the current directory.
using (var sftp = new SftpClient(host, username, password))
{
sftp.Connect();
var files = sftp.ListDirectory(remoteDirectory);
foreach (var file in files)
{
Console.WriteLine(file.FullName);
}
}
}
Upload File
/// <summary>
/// This sample will upload a file on your local machine to the remote system.
/// </summary>
public void UploadFile()
{
string host = "";
string username = "";
string password = "";
string localFileName = "";
string remoteFileName = System.IO.Path.GetFileName(localFile);
using (var sftp = new SftpClient(host, username, password))
{
sftp.Connect();
using (var file = File.OpenRead(localFileName))
{
sftp.UploadFile(remoteFileName, file);
}
sftp.Disconnect();
}
}
Download File
/// <summary>
/// This sample will download a file on the remote system to your local machine.
/// </summary>
public void DownloadFile()
{
string host = "";
string username = "";
string password = "";
string localFileName = System.IO.Path.GetFileName(localFile);
string remoteFileName = "";
using (var sftp = new SftpClient(host, username, password))
{
sftp.Connect();
using (var file = File.OpenWrite(localFileName))
{
sftp.DownloadFile(remoteFileName, file);
}
sftp.Disconnect();
}
}
---------------------------------------------------------
2) Another alternative library is WinSCP
---------------------------------------------------------
With the follwing example:
using System;
using WinSCP;
class Example
{
public static int Main()
{
try
{
// Setup session options
SessionOptions sessionOptions = new SessionOptions
{
Protocol = Protocol.Sftp,
HostName = "example.com",
UserName = "user",
Password = "mypassword",
SshHostKeyFingerprint = "ssh-rsa 2048 xx:xx:xx:xx:xx:xx:xx:xx:xx:xx:xx:xx:xx:xx:xx:xx"
};
using (Session session = new Session())
{
// Connect
session.Open(sessionOptions);
// Upload files
TransferOptions transferOptions = new TransferOptions();
transferOptions.TransferMode = TransferMode.Binary;
TransferOperationResult transferResult;
transferResult = session.PutFiles(@"d:\toupload\*", "/home/user/", false, transferOptions);
// Throw on any error
transferResult.Check();
// Print results
foreach (TransferEventArgs transfer in transferResult.Transfers)
{
Console.WriteLine("Upload of {0} succeeded", transfer.FileName);
}
}
return 0;
}
catch (Exception e)
{
Console.WriteLine("Error: {0}", e);
return 1;
}
}
}
Found here and with more here.
Problem
I am trying to achieve the ftp/sftp through FtpWebRequest class in C# but not succeeded till now. I dont want to use any 3rd party free or paid dll. credentials are like - hostname = sftp.xyz.com - userid = abc - password = 123 I am able to achieve the ftp with Ip address but unable to acheive sftp for above hostname with credentials. For sftp I have enabled the EnableSsl property of FtpWebRequest class to true but getting error unable to connect to remote server. I am able to connect with Filezilla with the same credentials and hostname but not through code. I observed filezilla, it changes the host name from sftp.xyz.com to sftp://sftp.xyz.com in textbox and in command line it changes the userid to abc@sftp.xyz.com I have done the same in code but not succeeded for sftp. Please need urgent help on this. Thanks in advance. Below is my code so far: ``` private static void ProcessSFTPFile() { try { string[] fileList = null; StringBuilder result = new StringBuilder(); string uri = "ftp://sftp.xyz.com"; FtpWebRequest ftpRequest = (FtpWebRequest)WebRequest.Create(new Uri(uri)); ftpRequest.Method = WebRequestMethods.Ftp.ListDirectoryDetails; ftpRequest.EnableSsl = true; ftpRequest.Credentials = new NetworkCredential("abc@sftp.xyz.com", "123"); ftpRequest.UsePassive = true; ftpRequest.Timeout = System.Threading.Timeout.Infinite; //ftpRequest.AuthenticationLevel = Security.AuthenticationLevel.MutualAuthRequested; //ftpRequest.Proxy = null; ftpRequest.KeepAlive = true; ftpRequest.UseBinary = true; //Hook a callback to verify the remote certificate ServicePointManager.ServerCertificateValidationCallback = new RemoteCertificateValidationCallback(ValidateServerCertificate); //ServicePointManager.ServerCertificateValidationCallback = ((sender, certificate, chain, sslPolicyErrors) => true); FtpWebResponse response = (FtpWebResponse)ftpRequest.GetResponse(); StreamReader reader = new StreamReader(response.GetResponseStream()); string line = reader.ReadLine(); while (line != null) { result.Append("ftp://sftp.xyz.com" + line); result.Append("\n"); line = reader.ReadLine(); } if (result.Length != 0) { // to remove the trailing '\n' result.Remove(result.ToString().LastIndexOf('\n'), 1); // extracting the array of all ftp file paths fileList = result.ToString().Split('\n'); } } catch (Exception ex) { Console.WriteLine(ex.Message.ToString()); Console.ReadLine(); } } public static bool ValidateServerCertificate(object sender, X509Certificate certificate, X509Chain chain, SslPolicyErrors sslPolicyErrors) { if (certificate.Subject.Contains("CN=sftp.xyz.com")) { return true; } else { return false; } } ```