Async file upload using JQuery, FormData and ASP.NET Web Api

This tutorial explains how to upload files to Wep Api with ajax and FormData.
The source code is available on GitHub.

Let's first create the Wep Api controller that handles the request.

[HttpPost]
public async Task<IHttpActionResult> Post()  
{
  try
  {
    if (!Request.Content.IsMimeMultipartContent())
    {
      return BadRequest("Not Mime Multipart Content");
    }

    var provider = new MultipartMemoryStreamProvider();

    await Request.Content.ReadAsMultipartAsync(provider);

    var path = Path.Combine(AppDomain.CurrentDomain.BaseDirectory, "Upload");

    foreach (var file in provider.Contents)
    {
      var fileName = Path.GetFileName(file.Headers.ContentDisposition.FileName.Trim('\"'));
      var fullPath = Path.Combine(path, fileName);
      var buffer = await file.ReadAsByteArrayAsync();
      File.WriteAllBytes(fullPath, buffer);
    }

    return Ok();
  }
  catch (Exception ex)
  {
    return InternalServerError(ex);
  }
}

The IsMultipartContent method checks whether the request contains a multipart MIME content. If not, the controller returns HTTP status code 400 (BadRequest).

The MultipartFormDataStreamProvider is a helper object that allocates file streams for uploaded files. ReadAsMultipartAsync method extracts all of the parts and writes them into the streams provided by the MultipartFormDataStreamProvider.

Contents property of the provider contains now the uploaded files. For each file we can use Headers to access Content-Disposition.

Now that the server code is in place we can add a file input to the page.

<input id="myFile" name="myFile" type="file" />  

It's time for some JavaScript. We can send the ajax request using JQuery and FormData which is a new interface introduced in XMLHttpRequest Level 2. FormData represents an ordered collection of entries. Each entry has a name and value. It's a set of key/value pairs representing form fields and their values.

$(document).ready(function () {
  $('#myFile').change(function () {
    var file = this.files[0];

    var formData = new FormData();
    formData.append('MyFile', file);

    $.ajax({
      type: 'POST',
      url: 'api/files',
      data: formData,
      contentType: false,
      processData: false,
      success: function () {
        alert('File uploaded successfully!');
      },
      error: function () {
        alert('OOOPS something went wrong!');
      }
    });
  });
});

Note that contentType and processData are required to be set to false to prevent the automatic processing of data. The default behaviour is converting the data into a string.

The source code is available on GitHub.

comments powered by Disqus