Facebook C# SDK - Upload Progress and Cancellation

(This feature requires Facebook C# SDK v5.1 at minimum.)

Recently Facebook supported uploading videos using graph api and multiple file uploads in a single batch request which have been both supported in the Facebook C# SDK. Though these are great features that enables us (the developers) to write cool apps using these api, you will soon notice the lack of user experience you can provide. Let us say you want to upload 10 photos each totaling up to 20mb (and assuming you don’t have the best internet speed) it would take quite some time for the upload to finish. Wouldn’t it be great if you could provide a sort of progress bar to the user? What if the user got an urgent phone call and need to go somewhere else and cancel the photo upload? Well starting from v5.1 these scenarios have been answered.

So first make sure you are at least on v5.1 if you aren’t.

(You can see this full working sample in the source code Samples\CS-WinForms.sln or Samples\CSWinFormsUploadProgressAndCancel.sln file prior to v5.2)

Here is an existing code that you would use prior to v5.1

var mediaObject = new FacebookMediaObject
{
    ContentType = "image/jpeg",
    FileName = Path.GetFileName(_filename)
}
.SetValue(File.ReadAllBytes(_filename));

var fb = new FacebookClient(_accessToken);
fb.PostCompleted += fb_PostCompleted;
fb.PostAsync("/me/photos", new Dictionary<string, object> { { "source", mediaObject } });

The above code uses a simple graph api photo upload as you would. (As for uploading 10 photos in a single batch request that I mentioned above is for your you to try it out Smile and get familiar with the new upload progress and cancellation apis).

Nothing fancy here. It just creates the media object and sets the value from the file and do a post to “/me/photos”.

To support the upload progress, you will need to add and event handler called UploadProgressChanged which will be called every time the progress changes. v5.1 also introduces a new event argument called FacebookUploadProgressChangedEventArgs. It contains useful information such as the progress percentage, number of bytes sent and total bytes to send.

fb.UploadProgressChanged += fb_UploadProgressChanged;

public void fb_UploadProgressChanged(object sender, FacebookUploadProgressChangedEventArgs e)
{
    progressBar1.BeginInvoke(
    new MethodInvoker(() =>
    {
        var totalBytesToSend = e.TotalBytesToSend;
        var bytesSent = e.BytesSent;
        var state = e.UserState;
        progressBar1.Value = e.ProgressPercentage;
    }));
}

progressBar1 is a standard WinForms control. Notice that I use BeginInvoke when I need to update the gui.

So now what about cancellation?

fb.CancelAsync() and that is it. Simple as it can be.

If want to add cancellation you might want to update your existing PostCompleted method. Make sure to check e.Cancelled first before anything else. You can then extract more information about the cancellation by checking the e.Error.

public void fb_PostCompleted(object sender, FacebookApiEventArgs e)
{
    if (e.Cancelled)
    {
        var cancellationError = e.Error;
        MessageBox.Show("Upload cancelled");
    }
    else if (e.Error == null)
    {
        // upload successful.
        MessageBox.Show(e.GetResultData().ToString());
    }
    else
    {
        // upload failed
        MessageBox.Show(e.Error.Message);
    }
}

Known issues on cancellation:

If you are using cancellation and call the CancelAsync() method, there are times when the request is completed and facebook has already sent you the response but you still get e.Cancelled as true. Since in .NET we can’t get the response on the HttpWebRequest which has been aborted, the Facebook C# SDK has no idea about whether the request was completed or not if the request was cancelled as the HttpWebResponse is always returned as null. Therefore, the SDK set the e.Cancelled as true.