FTP Upload in .NET - You ain't need no libraries

on June 28th, 2008 at 3:06pm 11 responses

Lately I've been asked about doing FTP related stuff in .NET .

There appear to be many "Ftp Clients" out there on CodeProject and other sites.

I really don't get 'em.

They are simple a leaky abstraction on top of straightforward BCL classes.

 

So what my solution is?

   1:  public void Upload(string server, int port, string targetFolder, string fileName, string username, string password, bool isActive)
2: {
3: var url = string.Format(
4: "ftp://{0}:{1}{2}/{3}", server, port, targetFolder, fileName)
5: using (var ftp = (FtpWebRequest)WebRequest.Create(url))
6: {
7: ftp.Credentials = new NetworkCredential(username, password);
8: ftp.KeepAlive = false;
9: ftp.UseBinary = true;
10: ftp.Method = WebRequestMethods.Ftp.UploadFile;
11: if (isActive)
12: ftp.UsePassive = false;
13:  
14: using (var writer = new BinaryWriter(ftp.GetRequestStream()))
15: writer.Write(File.ReadAllBytes(fileName));
16: }
17: }

 

This basic notepad code covers most of the functionality in FtpWebRequest. You can easily set Binary/ASCII, Active/Passive, Credentials and whatnot.

 

Alternatively, in some cases you can just spawn a ftp.exe process with a simple ftp script. Anyway you can rid yourself from unneeded leaky abstractions.

codegecko codegecko on January 26th, 2009 at 9:10am
Awesome code - was looking for a straightforward upload example and yours is just the ticket :-)
Ken Egozi Ken Egozi on January 28th, 2009 at 1:37pm
@Codegecko - I'm glad you liked it and found it useful.
Anon Anon on April 28th, 2009 at 1:46am
Good point on keeping it lean, but their code works and yours doesn't. Not only doesn't it compile, but the code isn't even correct.As a start, the url is incorrect, and FtpWebRequest/WebRequest do not support IDisposable (although GetRequestStream() does)
Ken Egozi Ken Egozi on April 29th, 2009 at 3:09am
@Anon, please don't be petty.1. fixing the URL should be pretty strait-forward and is anyway specific to a use-case. I guess that 99% of my readers can deal with that.2. the other compile errors (missing colon on the url line, and removing the 'using' from the creation of the ftp request) is something that, again, is fixed by anyone in about 2 seconds.even my fat, idiot cat can take this code sample and get it to work in under a minute.And most of all - you have missed the whole point. I never said anywhere that I have just created the best 3rd-party FTP library ever. I just said that *you don't need one*. As in - you can use the stuff in the BCL to get what you need without external dependencies that gives you virtually nothing, and cost you in integration, learning curve (for you and future devs), research time, and future compatibility issues. Anyway - I'm glad you enjoy my writings. ;)
glen glen on November 10th, 2009 at 4:03pm
It doesn't even compile. Can you please fix the syntax errors first ?
Ken Egozi Ken Egozi on November 10th, 2009 at 6:32pm
@Glen - are you for real?
Tony Cheethan Tony Cheethan on February 12th, 2010 at 1:15pm
"Could you please write a complete ftp application for me? I'm too lazy to do my own code, so I want to steal yours.";)Very helpful, thanks a lot!
That Guy That Guy on April 6th, 2010 at 9:15am
// Fixed version: public static void Upload(string server, int port, string targetFolder, string fileName, string username, string password, bool isActive) { var url = string.Format("ftp://{0}:{1}{2}/{3}", server, port, targetFolder, fileName); var ftp = (FtpWebRequest)WebRequest.Create(url); ftp.Credentials = new NetworkCredential(username, password); ftp.KeepAlive = false; ftp.UseBinary = true; ftp.Method = WebRequestMethods.Ftp.UploadFile; if (isActive) ftp.UsePassive = false; using (var writer = new BinaryWriter(ftp.GetRequestStream())) writer.Write(File.ReadAllBytes(fileName)); }It's not that I'm lazy, it's just that I don't see the point in multiple people fixing the same bugs. For code literacy practice, here are some better ways to pass the time:1. Generalize the code to read from a stream instead, and overload it to accept files2. Allow uploading a file from somewhere other than the current dir (without surprising results)3. Don't read the entire file into memory first, stream it instead
b b on August 7th, 2012 at 8:23pm

It seems as if writer.Write(File.ReadAllBytes(fileName)); is executed asynchronously. I run the upload method in a BackgroundWorker, and it terminates very quickly without waiting at the writer.Write method. If I put writer.close() after the .Write line then it would wait, however it would timeout if I were uploading a large file.

public static void upload(string f) { if (!File.Exists(f)) throw new Exception("File does not exist."); string url = string.Format("ftp://{0}/{1}", ftpServer, new FileInfo(f).Name); FtpWebRequest fwr = (FtpWebRequest)FtpWebRequest.Create(url); fwr.Credentials = new NetworkCredential(ftpServerUserName, ftpServerPassword); fwr.Method = WebRequestMethods.Ftp.UploadFile; fwr.UseBinary = true; fwr.UsePassive = true; fwr.KeepAlive = false; BinaryWriter writer = new BinaryWriter(fwr.GetRequestStream()); writer.Write(File.ReadAllBytes(f)); writer.Flush(); }

How to make this code compatible with uploading large files?

Ken Egozi Ken Egozi on August 29th, 2012 at 6:12pm

@b, thanks for your input.

  1. the writer should be properly closed to be flushed. It is not that it is Async, just that the underlying Stream is stopped before all buffers are fully flushed. This could be solved by calling .Close (as you did).

  2. If the file is big it might not fit in the client's memory. The code shown here loads the whole file into memory first. it should instead open a Reader from the file and pipe the stream to the BinaryWriter of the ftp stream.

  3. It is also possible that the FTP call is timing out for a combination of large file and slow upload speed. You should be able to increase the timeout on the ftp client (see [http://www.sidesofmarch.com/index.php/archive/2012/04/06/damn-the-documentation-ftpwebrequest-timeout-default-value-is-not-infinite/][1])

Skara Skara on November 16th, 2012 at 12:10pm

Hi. Thanks for code. But I have a question. For me it's not working when I try to upload file to ftps server. I can't understand where to use certificate and passphrase? And its threw an exception 'unable to connect to the remote server'. I think it beacuse of not setting certificate and passphrase. Can you help me? Thanks.







Comment preview:

Follow

Statistics

Posts count:
447
Comments:
951