Sometimes you just want a simple function to perform a simple task. There are a lot of FTP libraries for free download on the Internet, but if you simply want to upload a file to an FTP server in C#, these libraries are overkill for that simple little task. That's what I thought when I browsed the web for such a simple little function. Maybe I'm slower than normal people, but I couldn't find any simple method on the web. They where all too complicated, so I thought to myself that I could do better.

Here's what I came up with:

private static void Upload(string ftpServer, string userName, string password, string filename)
   using (System.Net.WebClient client = new System.Net.WebClient())
      client.Credentials = new System.Net.NetworkCredential(userName, password);
      client.UploadFile(ftpServer + "/" + new FileInfo(filename).Name, "STOR", filename);

Then call the method with the right parameters, and you're set to go:

Upload("ftp://ftpserver.com", "TheUserName", "ThePassword", @"C:\file.txt");

Can it get any simpler than that?


Comment by  Jan Schreuder

Really smart code. I have my own Ftp library which uses the WinInet API. I migrated it from VB6 to VB.Net and later to C#. But if you just need to upload, this is a beauty!

Comment by G.G.W. Andustar

Great code, and yes, I have found exactly the same thing on the net. All I want to do is upload a file! Microsoft should keep a more rigorous example database like Sun keeps for its Java platform. It would help sort out allot of overkill problems like the one described.

G.G.W. Andustar

Comment by  Ivan Lora

I'm receiving this error:
The server returned an address in response to the PASV command that is different than the address to which the FTP connection was made.

What it could be?


Ivan Lora

Comment by  Edgar López


I'm using this tip, and i got this error "The remote server returned an error: (530) Not logged in."; I can access my ftp server from my browser but in my c# code it doesn't work.

Enviroment: Windows XP pro (spanish) SP2, VS2005, there is no proxies.

Ideas and suggestions are appreciated.



Edgar López

Comment by  Philip

Couldn't have agreed more with your explanation.

This small piece of code is exactly what I needed. Clean, simple and very direct.



Comment by  Nic

You might want to try this to solve the Passive FTP problem - just use the FTPWebClient in the WebClient's place and set UsePassiveFTP where required:

Class FTPWebClient : WebClient

public bool UsePassiveFTP = false;

protected override WebRequest GetWebRequest(Uri address)
FtpWebRequest req = (FtpWebRequest)base.GetWebRequest(address);
req.UsePassive = this.UsePassiveFTP;
return req;



Comment by Garnet R. Chaney

I've got a program that needs to create directories on remote FTP servers, and also upload files to those directories. I've written this to create the remote directories:

FtpWebRequest ftp = null;
FtpWebResponse resp = null;
ftp = (FtpWebRequest)FtpWebRequest.Create(sFullFtpUrl);
ftp.Credentials = new NetworkCredential(Username, Password);
ftp.Method = WebRequestMethods.Ftp.MakeDirectory;

resp = (FtpWebResponse)ftp.GetResponse();
Console.WriteLine("MKD status: {0}", resp.StatusDescription);

// Remember this directory so we don't try to create it again
CreatedDirectories.Add(sDir, 0);
catch (Exception exc)
Console.WriteLine("Create FTP directory "+sDir+" "+exc.Message);

// If the error is already exists, don't bother trying again...
CreatedDirectories.Add(sDir, 0);


This code works for a while (maybe dozens of calls), then it starts throwing "The Operation Has Timed Out". I am watching the messages log on the remote FTP site, and when the program is working, I see the logins/commands/logouts recorded... But when this routine starts timing out, I don't see anymore new connection or login messages.

In the exception routine, I can see that there is a private variable ftp.m_FtpWebResponse that has been set, although only "LastModified" and "ResponseUri" seem to be set. There is no way to get at it to try and call close on it.

I saw a similar problem to this with using the GetResponse to read webpages. If you remember to close the streams, but forget to close the WebResponse (as some examples show), eventually .NET stops return GetResponse. I monitored the network, and nothing was getting sent over the wire. It seems to be like there is an internal pool of objects that get used up.... I am worried that with FTP, getting exceptions (like directory already exists), might be leaving FtpWebResponse objects hanging open.

Stopping the program and restarting allows operation to continue again, at least for a while....

Let me know if you have any ideas on this problem of the Ftp GetResponse no longer being sent over the network.

Comment by deddy

Hi, I've tried your code, it worked perfectly on local server. but when I moved it to production IIS server, I got the "could not find part of path" kind of error. do you have any suggestion ??


Comment by Mads Kristensen

@deddy, the error has to do with the filename you feed the method. It could be because the relative paths are different on your production environment than on your local machine.

Comment by deddy

Hi, thanks for the quick response, but I'm still having trouble.
I'm using your code like this :

client.Credentials = new System.Net.NetworkCredential("", "");
client.UploadFile("ftp://myftpsite/" + new FileInfo(FileUpload1.PostedFile.FileName.ToString()).Name, "STOR", @FileUpload1.PostedFile.FileName.ToString());

can you give me some enlightment.
I dont set any username nor password on my ftpsite yet,
so this code is working fine on local server.
can you tell me how to make it works too on IIS server?


Comment by Chris

Yum yum... another ftp username and password flying through the web just waiting to be consumed by those pesky hackers. Mads, you really shouldn't be using FTP for anything other than anonymous file posting... actually it's not my place to tell you what you should and shouldn't be doing, 8~)

But seriously folks, why on earth would you want your credentials sent out into the eWorld in the clear? There are many alternatives available that you can use in replace of FTP that will protect your credentials. Perhaps you could have a look at my recent post that talks about this issue (www.dscoduc.com/.../...SH-to-manage-your-blog.aspx).

And as for quick transfers from you could always explore plink.exe and pscp.exe (www.chiark.greenend.org.uk/.../download.html) for those command level uploads.

When Windows 2008 comes out there will be a sFTP based on SSL available that would probably be a good fit for you also...

Comment by Alex

Very good and simple, but I have one question.

"client.UploadFile(ftpServer + "/" + new FileInfo(filename).Name, "STOR", filename);"

Why did you write "STOR"? I get an webexception error...


Comment by Alex

using System;
using System.Collections;
using System.Configuration;
using System.Data;
using System.Linq;
using System.Web;
using System.Web.Security;
using System.Web.UI;
using System.Web.UI.HtmlControls;
using System.Web.UI.WebControls;
using System.Web.UI.WebControls.WebParts;
using System.Xml.Linq;
using System.IO;
using System.Net;
using System.Text;

public partial class Default2 : System.Web.UI.Page
string filen, uppladdurl,anvNamn, losen;

protected void Page_Load(object sender, EventArgs e)
uppladdurl = @"ftp://gallery.mypage.se/ImageBank/images";
losen = "1234";
anvNamn = "gallery";
protected void Button1_Click(object sender, EventArgs e)
filen = FileUpload1.FileName;

Upload(uppladdurl, anvNamn, losen, filen);
private static void Upload(string ftpServer, string userName, string password, string filename)
using (System.Net.WebClient client = new System.Net.WebClient())
client.Credentials = new System.Net.NetworkCredential(userName, password);
client.UploadFile(ftpServer + "/" + new FileInfo(filename).Name, filename);


Don´t know what I´m doing wrong. Could someone help pls?