13

I need some guidance. I need to develop a customizable FTP in C# that should be configured using App.Config file. Also, the FTP should push the data to any server from any client again depends on config file.

I will appreciate if someone can guide, if there is any API or any other useful suggestion, or move me in the right direction.

Edward Brey
  • 40,302
  • 20
  • 199
  • 253
user421963
  • 131
  • 1
  • 1
  • 4

3 Answers3

20

You can use FtpWebRequest; however, this is fairly low level. There is a higher-level class WebClient, which requires much less code for many scenarios; however, it doesn't support FTP/SSL by default. Fortunately, you can make WebClient work with FTP/SSL by registering your own prefix:

private void RegisterFtps()
{
    WebRequest.RegisterPrefix("ftps", new FtpsWebRequestCreator());
}

private sealed class FtpsWebRequestCreator : IWebRequestCreate
{
    public WebRequest Create(Uri uri)
    {
        FtpWebRequest webRequest = (FtpWebRequest)WebRequest.Create(uri.AbsoluteUri.Remove(3, 1)); // Removes the "s" in "ftps://".
        webRequest.EnableSsl = true;
        return webRequest;
    }
}

Once you do this, you can use WebClient almost like normal, except that your URIs start with "ftps://" instead of "ftp://". The one caveat is that you have to specify the method parameter, since there won't be a default one. E.g.

using (var webClient = new WebClient()) {
    // Note here that the second parameter can't be null.
    webClient.UploadFileAsync(uploadUri, WebRequestMethods.Ftp.UploadFile, fileName, state);
}
Edward Brey
  • 40,302
  • 20
  • 199
  • 253
  • From the comments of [a duplicate answer](https://stackoverflow.com/a/31432519/1869660): To auto-accept any certificates the client may encounter, this works: `ServicePointManager.ServerCertificateValidationCallback += (sender, certificate, chain, sslPolicyErrors) => true;` – Sphinxxx Jan 16 '18 at 00:21
  • 2
    @Sphinxxx Just be aware that blindly accepting any server certificate leaves you vulnerable to a man-in-the-middle attack. – Edward Brey Jan 16 '18 at 00:26
  • Yes, it's not the most elegant solution. Do you have a safer alternative? – Sphinxxx Jan 16 '18 at 00:35
  • 2
    Normally, you just ensure that the server has a SSL certificate that matches its host name, just as you would for any HTTPS traffic. If you can't do that, you can [validate a self-signed certificate](https://stackoverflow.com/a/526803/145173). – Edward Brey Jan 16 '18 at 00:42
7

The accepted answer works, indeed. But I find it too cumbersome to register a prefix, implement an interface, and all that stuff, particularly, if you need it just for one transfer.

FtpWebRequest is not that difficult to use. So I believe that for one-time use, it's better to go this way:

FtpWebRequest request =
    (FtpWebRequest)WebRequest.Create("ftp://ftp.example.com/remote/path/file.zip");
request.Credentials = new NetworkCredential("username", "password");
request.EnableSsl = true;
request.Method = WebRequestMethods.Ftp.UploadFile;  

using (Stream fileStream = File.OpenRead(@"C:\local\path\file.zip"))
using (Stream ftpStream = request.GetRequestStream())
{
    fileStream.CopyTo(ftpStream);
}

The key is the EnableSsl property.


For other scenarios, see:
Upload and download a binary file to/from FTP server in C#/.NET

Martin Prikryl
  • 188,800
  • 56
  • 490
  • 992
2

We use edtFTPnet with good results.

Adriaan Stander
  • 162,879
  • 31
  • 289
  • 284