Uploading Files using AJAX

Normally, if you want to to upload files through a website you would use a <form> element with enctype=”multipart/form-data” that posts the file from a nested file-<input> element to the specified action (in ASP.NET MVC you would receive that file on the server side by means of a HttpPostedFileBase variable as argument of your action method).

But if you don’t have or don’t want to use a <form> for some reason you have to find other ways to upload a file.

The obvious way would be to assemble and submit a invisible form with Javascript when the user triggers the upload event. To make this work properly you would also have to create an <iframe> as “target” for the <form> that receives the response. The advantage of this method is that it works with all browsers.

Another approach would be to use AJAX, that is using an XMLHttpRequest object. This is also very simple and done in a few lines of Javascript code:

var xhr = new XMLHttpRequest();
xhr.open("POST", url, true); // method, url, async
xhr.setRequestHeader("Cache-Control", "no-cache");
xhr.setRequestHeader("X-File-Name", file.fileName);
xhr.setRequestHeader("X-File-Size", file.fileSize);
xhr.setRequestHeader("Content-Type", "multipart/form-data");

In the above code the “url” would be the “Controller/Action” to which the Request is posted to and the “file” can be extracted from any file-<input> element.

The “X-File-Name” and “X-File-Size” are just self-chosen optional parameters that will be appended to the RequestHeader. That way you can send additional data with the Request.

Again, the “Content-Type” has the be “multipart/form-data” as we’re sending a file/binary data.

The “Cache-Control” is set to “no-cache”, to bypass server cache, so it cannot respond with a “304 Not Modified” response header and skip sending the data.

Finally, we have to subscribe to the “onreadystatechange” event in order to receive the Response from the server:

xhr.onreadystatechange = function() {
    if (xhr.readyState == 4) {      // completed
        if (xhr.status == 200) {    // OK
            var response = xhr.responseText;
            // do something

This solution should work quite well. But if you are using jQuery I would recommend you to use its .ajax() function instead. jQuery does several optimizations for different browsers and also takes over error handling.

    beforeSend: function (xhr) {
        xhr.setRequestHeader("Cache-Control", "no-cache");
        xhr.setRequestHeader("X-File-Name", file.fileName);
        xhr.setRequestHeader("X-File-Size", file.fileSize);
        xhr.setRequestHeader("Content-Type", "multipart/form-data");
    type: 'POST',
    url: url,
    processData: false,
    data: file,
    success: function (data, textStatus, xhr) {
        // do something
    error: function (xhr, textStatus, errorThrown) {
        // do something

We’re modifying the XMLHttpRequest to be sent in the “beforeSend” callback and set all needed options.
It’s important to set “processData” to “false”. This will prevent jQuery to transform the data to the default content type “application/x-www-form-urlencoded”.

Server Side:

A server side action method could then look like this:

public ActionResult UploadFile()
    bool success = false;
    string message = String.Empty;

    // Read custom attributes
    string fileName = Request["HTTP_X_FILE_NAME"];  // notice the "HTTP_" prefix
    string fileSize = Request["HTTP_X_FILE_SIZE"];

        // Read input stream from request
        byte[] buffer = new byte[Request.InputStream.Length];
        int offset = 0;
        int cnt = 0;
        while ((cnt = Request.InputStream.Read(buffer, offset, 10)) > 0)
            offset += cnt;
        // Save file
        using (FileStream fs = new FileStream(@"C:\Path\To\Save\File\" + fileName, FileMode.Create))
            fs.Write(buffer, 0, buffer.Length);
        // Or in one line
        // System.IO.File.WriteAllBytes(@"Path\To\Save\File\" + fileName, buffer);

        success = true;
        message = "Success...";
    catch (Exception)
        success = false;
        message = "Error...";

    // Create JSON Response
    var jsonData = new
        success = success,
        message = message

    return Json(jsonData);


4 Responses to “Uploading Files using AJAX”

  1. clasificado Says:


  2. peter Says:

    i have one question, Where is file in data:file. Plz help

  3. Jay Says:

    Hello, thanks for this! Can you explain how to get “file” in the jquery instance to pass to the ajax post?

  4. Wi Ki Says:

    Hi. Thanks for this. It was really nice. There is one problem though, the uploaded file seems to be of an invalid type and can not be opened. Here is the code.

    var encodedFileName = Md5Hash(DateTime.Now.ToString(“F”) + ” – ” + fileName) + “.” + fileName.Split(‘.’)[1];

    // save the file
    using (var fs = new FileStream(Path.Combine(Server.MapPath(“~/Images/Uploads”), encodedFileName), FileMode.Create))
    fs.Write(buffer, 0, buffer.Length);

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s

%d bloggers like this: