Uploading files to ftp using C# .NET 3.5 or 4.5

C# .NET has more than couple ways of uploading files via ftp. The older method using the web request class felt cumbersome, but was effective. It involved a lot of key strokes, had a lot of moving parts to it, and wasn’t exposed well for asynchronous operations (although could). With .NET 4.0, Microsoft introduced the concept of Tasks, which greatly simplified this process, and in .NET 4.5, expanded even further. Through this new pattern, it’s easier to achieve the same results with more simplified syntax.

I recently got into using this pattern and I wanted to share first the older way of uploading files to ftp and then using the newer, task-based model.

Okay! So first…

Using .NET 3.5:

var file = new FileInfo("fileToUpload.txt");
var ftp = (FtpWebRequest)WebRequest.Create("ftp://127.0.0.1");
ftp.Credentials = new NetworkCredential("ftpUserName", "ftpPassword");

ftp.UseBinary = true;
ftp.UsePassive = true;
ftp.Method = WebRequestMethods.Ftp.UploadFile;

using (var fileStream = file.OpenRead())
{
    using (var stream = ftp.GetRequestStream())
    {
        int bufferSize = (int)Math.Min(fileStream.Length, 2048);
        var buffer = new byte[bufferSize];
        int bytesRead = -1, bytesWritten = 0;
        
        while (bytesRead != 0)
        {
            bytesRead = fileStream.Read(buffer, 0, bufferSize);
            stream.Write(buffer, 0, bufferSize);
            bytesWritten += bytesRead;
            Console.WriteLine(bytesWritten + " bytes written out of " + fileStream.Length);
        }
    }
}

So basically what we’re doing here is:

  1. Grabbing an instance of FileInfo, passing in the file path to the file we wish to upload (in this case, just the name since it’s in the same directory as the exe).
  2. Creating a new ftp web request. We explicitly cast it so we have access to the functionality of that class (such as UseBinary, UsePassive etc).
  3. Telling the request that we plan on using this request to upload a file via the Method property of FtpWebRequest.
  4. Opening a filestream to our file so we can get the bytes from it.
  5. Opening up a stream to our ftp server, allowing us to write our file to it.
  6. Creating a byte array buffer to store our bytes as we’re writing to the ftp server.

This process is cumbersome and requires quite a bit of keystrokes.

Now, using .NET 4.5, we can rewrite the same code like this.

Using .NET 4.5

var tasks = new List<Task>();

using (WebClient client = new WebClient())
{
    string ftpFilePath = "sample_file.txt";
    string localFilePath = ""; // Path to your local file
    client.Credentials = new NetworkCredential("ftpUserName", "ftpPassword");
    var task = client.UploadFileTaskAsync("ftp://127.0.0.1/" + ftpFilePath, localFilePath);
    tasks.Add(task);
}

Task.WaitAll(tasks.ToArray());

Already we can see this is a much cleaner solution, let’s break it down.

  1. First we create an list of tasks that will hold the functionality we tell it to (in this case to upload a file).
  2. Next we open up an instance to the WebClient class, pass in necessary credentials.
  3. Through the method UploadFileTaskAsync, we give it the absolute path of where we want our file to go, its name, and pass in the name to reference on our local machine, then add it to the list.
  4. Finally, this is where the magic happens. We make a call to Tasks static WaitAll method, converting our list to an array in the process.

The Task-based Asynchronous Pattern

So the thing to note here is WaitAll. What this method does is take in an array of Tasks, and execute them asynchronously, that is concurrently, as opposed to synchronously, or sequential. I could have easily of written it as tasks[0] or a single task, but the reason I made a list of tasks is the beauty of this pattern: we could create multiple tasks, store them in the array, and make this same call to WaitAll to upload multiple files at the same time! So not only is this newer method shorter and more clean, it has the added benefit of a simplified asynchronous model to follow. This is called the Task-based Asynchronous Pattern.

You could also make this code snippet awaitable, allowing the calling thread not to block and continue execution while it finishes. You would do this by changing Task.WaitAll to Task.WhenAll, putting await in front of the call, and marking the method it’s inside with the async keyword.

Wrapping Up

So hopefully this has been informative, if you’ve enjoyed reading please leave a comment below or see if I’ve made any mistakes or a better way of doing this I would love to hear it, thanks!