Click here to Skip to main content
14,212,594 members
Click here to Skip to main content
Tip/Trick
Posted 18 Dec 2015

Stats

20.6K views
392 downloads
6 bookmarked

File Upload Using Html5 File API & Ajax Post

,
Rate this:
4.60 (4 votes)
Please Sign up or sign in to vote.
4.60 (4 votes)
18 Dec 2015     CPOL    
Simple file upload using Html5 & Ajax post

Introduction

Recently, I had a requirement to implement a file upload using only JavaScript and Ajax post, without using the RequestContext object or the FormData objects. The requirement was to post user uploaded file to a WebApi method. The posted file should not be obtained using Request.Files collection or the uploaded file should not be sent using the FormData object from JavaScript. After several walk throughs of online articles, I came up with the below solution.

Using the Code

First the client part. The html page just contains a file upload control and a button control.

<input type="file" id="files" name="file" />
<button id="uploadbtn">Upload</button>

We define the click event of the upload button using jQuery:

$(document).ready(function () {
          $("#uploadbtn").click(readBlob);
      });

We define the readBlob and getB64Str functions as below:

function readBlob() {
          var files = document.getElementById('files').files;
          if (!files.length) {
              alert('Please select a file!');
              return;
          }

          var file = files[0];
          var blob = file.slice();

          var filetype = file.type;
          var filename = file.name;

          var reader = new FileReader();

          reader.onloadend = function (evt) {
              if (evt.target.readyState == FileReader.DONE) { // DONE == 2

                  var cont = evt.target.result
                  var base64String = getB64Str(cont);

                  var model = {
                      contentType: filetype,
                      contentAsBase64String: base64String,
                      fileName: filename
                  };

                  $.ajax({
                      url: '/api/File/ProcFile',
                      type: 'POST',
                      data: JSON.stringify(model),
                      processData: false,
                      async: false,
                      contentType: 'application/json',
                      complete: function (data) {
                          console.log(data.responseText);
                      },
                      error: function (response) {
                          console.log(response.responseText);
                      }
                  });
              }
          };

          reader.readAsArrayBuffer(blob);
}

function getB64Str(buffer) {
          var binary = '';
          var bytes = new Uint8Array(buffer);
          var len = bytes.byteLength;
          for (var i = 0; i < len; i++) {
              binary += String.fromCharCode(bytes[i]);
          }
          return window.btoa(binary);
}

There are many ways to convert ArrayBuffer to base64 string. One of them is used in the above code. It can be like below also:

var base64String = btoa(String.fromCharCode.apply(null, new Uint8Array(cont)));

The .readAsBinaryString is obsolete now and cannot be used.

The Model is a simple object as below:

public class FileModel
{
    public string contentType { get; set; }

    public string contentAsBase64String { get; set; }

    public string fileName { get; set; }

}

The WebApi method processes the posted data and creates the file server side from the base64 string and saves it in server.

[HttpPost]
public HttpResponseMessage ProcFile(FileModel filemodel)
{
    if (filemodel == null)
    {
        return new HttpResponseMessage(HttpStatusCode.BadRequest);
    }
    else
    {
        var filecontent = filemodel.contentAsBase64String;
        var filetype = filemodel.contentType;
        var filename = filemodel.fileName;

        var bytes = Convert.FromBase64String(filecontent);
        var savedFile = @"c:/temp/copy_of_" + filename;

        using (var file = new FileStream(savedFile, FileMode.Create))
        {
            file.Write(bytes, 0, bytes.Length);
            file.Flush();
        }

        return Request.CreateResponse(HttpStatusCode.OK, savedFile);
    }
}

The full code is attached to this tip. The solution was created using VS 2015. The packages were removed from zip to reduce the file size. Packages should be restored.

Point of Interest

The above code works for files upto 10 MB as far as I tested using Chrome. For large files, Chrome becomes unresponsive. I am looking at more efficient ways to convert ArrayBuffer to base64 string.

License

This article, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)

Share

About the Author

sazakir
Technical Lead
India India
.net developer

Comments and Discussions

 
QuestionProject Pin
Dewey18-Dec-15 16:04
memberDewey18-Dec-15 16:04 
Questionno pure code, this is jquery dependant Pin
Alejandro Barrada18-Dec-15 10:50
memberAlejandro Barrada18-Dec-15 10:50 
AnswerRe: no pure code, this is jquery dependant Pin
Dewey18-Dec-15 16:00
memberDewey18-Dec-15 16:00 
I agree that there is no need to use jQuery here, but it's easy to see how you can do this without jQuery.

I don't mind the use of jQuery because we generally include it anyway, but I do understand those that don't.

General General    News News    Suggestion Suggestion    Question Question    Bug Bug    Answer Answer    Joke Joke    Praise Praise    Rant Rant    Admin Admin   

Use Ctrl+Left/Right to switch messages, Ctrl+Up/Down to switch threads, Ctrl+Shift+Left/Right to switch pages.

Layout: fixed | fluid

Article Copyright 2015 by sazakir
Everything else Copyright © CodeProject, 1999-2019

Server Web01
Version 2.8.190619.2