Uploading Files Using the REST API and Client Side Techniques

Over the past few months I have, on several occasions, been asked how to upload a file to SharePoint using nothing more than JavaScript, HTML and the REST API. A few weeks ago, on a customer project, I was asked to do exactly that and was astonished to find that there is sparse documentation and even fewer examples out there on the Internet. For this reason, I have decided to write a post on how to use HTML 5 and JavaScript to upload files to a SharePoint 2013 document library.

Please Note: This technique is only supported in browsers that support the FileReader object of the File API. Currently this includes, but is not limited to, Internet Explorer version 10, Firefox version 3.6 and Chrome version 7 (information about the File API, including the FileReader object can be found here).

There are two specific areas that I will cover in this article; how to extract the file from the user’s machine and how to post this file off to the correct document library (including how to upload into a folder).Please note that this article does not cover the authentication aspect of uploading files over REST. If you are performing the upload from a SharePoint hosted app then this is taken care of by the app model. If you are performing an upload from another source then you will need to include an OAuth token (either as an App or as a user) with the request by setting an additional header (“authorization”).

Getting the file

Traditionally, uploading files is achieved by using a form that POSTs off to a web server which then handles the upload. This means that developers do not have to directly reach into the client’s file system to obtain the file. However this also means that you need to have access to a web server where you can handle the upload. In some situations, SharePoint hosted apps for example, the developer does not have access to this infrastructure and the upload must be handled inside the client’s web browser.

Advancements in the JavaScript File API allow developers to access the local file system using a standard input tag. The magical part is that you can access the file contents without having to perform a post back. The JavaScript code below shows how you can read the contents of a file (assuming that you have an input tag of type file inside the HTML document with an ID of fileSelectorInput).

  1. var fileInput = $(‘#fileSelectorInput’)[0];
  2. var reader = new FileReader();
  3. reader.onload = function (result) {
  4.     var fileData = ;
  5.     var byteArray = new Uint8Array(result.target.result)
  6.     for (var i = 0; i < byteArray.byteLength; i++) {
  7.         fileData += String.fromCharCode(byteArray[i])
  8.     }
  9. };
  10. reader.readAsArrayBuffer(fileInput.files[0]);

The example first uses jQuery to obtain a reference to the input tag on the page. A new FileReader object is then created and the readAsArrayBuffer function is called on the FileReader passing in a reference to the first file in the list.

The onload function contains the contents of the file (inside result.target.result) however this is in the format of an ArrayBuffer. To upload the file to SharePoint this must be converted into a string which can then be set as the body of a POST operation. This can be done by iterating through the array and building up a string using the string.fromCharCode() function. Details of this encoding method can be found in this MSDN article.

Performing the upload

Performing the actual upload is relatively simple. In the example code at the end of this article I will be using the cross domain library provided with SharePoint 2013 to perform uploads from within a SharePoint Hosted App. This library allows for cross domain calls from pages in the App web to the parent site. I will also show the endpoints required to upload files without the cross domain library.

Uploading to the root folder of a document library (without the cross domain library)

This is probably the simplest endpoint that I will cover. TargetSite needs to be replaced with the URL of the SharePoint site (e.g. https://sharepoint.com/sites/site). Additionally, the final two parameters (TargetLibrary and TargetFileName) need to be replaced with the appropriate values. The URL is:

TargetSite/_api/web/lists/getByTitle(@TargetLibrary)/RootFolder/Files/add(url=@TargetFileName,overwrite=’true’)?@TargetLibrary=’LibraryName‘&@TargetFileName=’Target File Name

Uploading to the root folder of a document library (with the cross domain library)

If you would like to perform the upload from a SharePoint hosted App you will need to use the cross domain library to overcome cross domain issues. This can be done by modifying the start of the URL and adding an additional parameter (TargetSite) which needs to be replaced with the URL of you target site (e.g. https://sharepoint.com/sites/site). You will also need to replace the AppWebUrl section with the URL of your AppWeb. All other parameters should stay the same. The URL is:

AppWebUrl/_api/SP.AppContextSite(@TargetSite)/web/lists/getByTitle(@TargetLibrary)/RootFolder/Files/add(url=@TargetFileName,overwrite=’true’)?@TargetSite=’Target site URL’&@TargetLibrary=’LibraryName’&@TargetFileName=’Target File Name 

Uploading to a folder within a document (without the cross domain library)

Uploading to a folder in a document library is fairly similar to uploading to the root folder. Again I will show two examples (one with and one without the cross domain library). The simplified version (without the cross domain library) can be performed using the URL below. You will need to replace the various components in the same way as you would for uploading to the root folder (mentioned previously). Also note the addition of a TargetFolder parameter and the change to URL to include the folder. The URL is:

TargetSite/_api/web/lists/getByTitle(@TargetLibrary)/RootFolder/folders(@TargetFolderName)/files/add(url=@TargetFileName,overwrite=’true’)?@TargetLibrary=’LibraryName’&@TargetFolder=’Target Folder Name’&@TargetFileName=’Target File Name

Uploading to a folder within a document (with the cross domain library)

You can also use the cross domain library to upload files to a folder within a document library. The URL needs to be modified slightly (in the same way as before) to redirect the message to the AppWeb and to include the TargetSite parameter. The URL is:

AppWebUrl/_api/SP.AppContextSite(@TargetSite)/web/lists/getByTitle(@TargetLibrary)/RootFolder/folders(@TargetFolderName)/files/add(url=@TargetFileName,overwrite=’true’)?@TargetSite=’Target site url’&@TargetLibrary=’LibraryName’&@TargetFolder=’Target Folder Name’&@TargetFileName=’Target File Name 

Required Headers/Options

In addition to ensuring you use the correct endpoint and encoding, it is important to ensure that the correct headers/options are set on the request. The actual request should be sent as a POST operation and the content type, headers, content length and binary string request body options must be set.

Accept: The Accept option must be set equal to “application/json; odata=verbose” inside the headers of the request.
Digest Value: The digest value should be set equal to the digest value obtained from SharePoint. This should also be set in the headers section of the request. The digest value can be read from SharePoint pages or be requested from the app web. More information about digest values can be found here under the heading “Writing data by using the REST interface”.
Content Type: The content type of “application/json; odata=verbose” should be set on the request
Body: The body should be set equal to the file contents encoded as per the description in the MSDN article here.
BinaryStringRequestBody: The option “binaryStringRequestBody” should be set equal to true. This informs SharePoint that the body of the message contains binary data.
Content Length: The content length of the request should be set equal to the length of the body. Note: if you are using the request executor then the content length is optional, if you are uploading directly (without the request executor) then you must set the content length otherwise SharePoint will reject the request.


In summary, performing uploads via the REST API using only client side technologies is not only possible, but is actually quite simple. We have looked at how to extract the file from the user’s machine, generate the correct endpoint and set the correct headers/options on the request. When you put all of this together you can upload binary files to SharePoint from the end users web browser without having to process the files server side. This means that in situations such as SharePoint hosted Apps where developers do not have access to server side code uploads can still be performed. Furthermore in situations where you do have access to server side code you can still use the endpoints mentioned to upload files using the REST API.

The source code below contains a working example (in the form of a SharePoint hosted App).


Source Code

The following downloadable source code contains a working example of uploading files over REST. The sample is contained within a SharePoint hosted app and you will need to have Visual Studio 2012 installed to be able to run it. To run the example you will need to configure the SiteUrl of the project to point to a SharePoint 2013 developer site. To do this click on the project in solution explorer and open up the properties task pane. Enter the URL of your site into the SiteUrl box and then press F5.

Upload Over REST Example.zip

Comments (33)

  1. Paul Tavares (@paul_tavares) says:

    Excellent post and something I have been wondering if this could be done in JS – even if using the WebServices API… I'll have to try and see if I can also get it done with WebServices. Once i get the file into base64 string, I should be able to do it.

    I have created "similar" solutions for SP2007 and SP2010 which basically use the upload page inside a manipulated iframe… The user never leaves the page while the page is uploaded.

    I currently have it as a jQuery pluin in my SPWigets library – here: purtuga.github.io/SPWidgets

  2. MBR says:

    Hmm, the csproj looks well formed, but the UploadOverREST.csproj say "unsupported" for me in VS2010 and 2012.

  3. RWP says:

    Can this be done in Sharepoint 2010?

  4. L360 says:

    Excellent post… Thanks I am able to upload documents using this format. But I have a question : Can we upload document with metadata columns using this Rest api,javascript and html5?

  5. Ryan says:

    Great article, works like a charm. However, I am also interested in including an identifier metadata along with my document when uploading. Is this possible?

  6. Katie says:

    Many thanks for a great example.

  7. CyberPine says:

    Great Post!   Any reason this cannot be implemented through NAPA?  Shame IE 7+ don't support this.

  8. CyberPine says:

    If somebody get's this working via NAPA and the Current Site's document Library root folder PLEASE SHARE the full source and code.  Ideally, I'd like to have a function that can set meta data columns and do some validation (restrict file type, rename the file, check if a combination (name and metadata ) is already there before it uploads.  This would be extremely valuable as we have many interfaces where end users are only upload a file with some Identification data.

  9. JC Net says:

    Interested in this too..  I made an attempt to get this code working on NAPA under a ClientWebPart.aspx page.  Had to add a reference jQuery  1.8.2 and tweak some of the code (expected === and new  in some places).  the form comes up and it locates files.  But I get  "Oooooops… it looks like something went wrong uploading your file." from IE 10 and   Chromebook. I confirmed it's getting a good targetsiteurl, but #__REQUESTDIGEST does not resolve to anything…not sure what this is.  

  10. Ramesh Pandey says:

    This line is a problem … check *** how can a large file of say 2-3MB be handled or even bigger, what about multiple large files.. would browser be able to handle all that ?

    The onload function contains the contents of the file (inside result.target.result) however this is in the format of an ArrayBuffer. To upload the file to SharePoint this *** must be converted into a string **** which can then be set as the body of a POST operation.

  11. mahesh says:


    thanks for the post

    i am bit confused about where to add my office365 site url

    can you please tell me how to and where to add url to jquery file in the sample solution

    Thanks in Advance


  12. Kris says:

    Great Post, thanks for the direction.  Have you ran into uploading 0kb files before?… I'm trying to post to an image library, everything succeeds but when I check the file, it's 0Kb.  Any ideas?

  13. prasadwt says:


    Would like to know whether a managed metadata column can be inserted into the doc lib along with the file [ .doc/.xls/.txt/.pdf .. etc ] from a remote system  using REST API.

    help is  appreciated.



  14. Mike Sharepoint says:


    Great post.

    I am having a problem when trying to upload large files, the script is blocking the page and nothing happens next.

    Do you have any idea on how to resolve this ?


  15. Ashish Padhy says:


    Pretty great post. If i need to upload a file to sub folder of a folder in the library. Can i add the URL of the folder in the FolderName property.

    Eg. I  have folder 'A' in library 'L'. There is a folder B inside folder A. I need to upload file inside folder B.  

  16. Alfonso says:

    Thanks for your post!

    One thing I have found is Digest Value is managed by RequestExecutor so it has not to be set as said in msdn.microsoft.com/…/jj164022(v=office.15).aspx. In fact, if your code is run as a app part it fails, because $("#__REQUESTDIGEST") is undefined.

  17. Mihir says:

    Thak you so much.. it was really helpful

  18. J Crosby says:

    This was very helpful but I seem to have found a flaw.  When attempting to upload video the file uploads but a 404 error is return back to the executor.

    I used the following template:

    AppWebUrl/_api/SP.AppContextSite(@TargetSite)/web/lists/getByTitle(@TargetLibrary)/RootFolder/Files/add(url=@TargetFileName,overwrite='true')?@TargetSite=’Target site URL’&@TargetLibrary=’LibraryName’&@TargetFileName=’Target File Name’

  19. Rahul Dayal says:

    Not able to upload file to office 365 working fine with my on-premise server. can you help me with that.  

  20. Joseph LeMay says:

    Here it is working with Office 365 uploading an attachment to a list item using cross domain. It's virtually the same as this blog's solution except for the REST URI. Of course, substitute your own list name for what I have in here (DOH%20News%20Drafts).

    function processUpload(fileInput) {

       var reader = new FileReader();

       reader.onload = function (result) {

           var fileName = '',

           fileData = '';

           var byteArray = new Uint8Array(result.target.result)

           for (var i = 0; i < byteArray.byteLength; i++) {

               fileData += String.fromCharCode(byteArray[i])


           // once we have the file perform the actual upload

    fileName = fileInput.name;

           performUpload(fileName, fileData);




    function performUpload(fileName,  fileData) {

    // see blogs.msdn.com/…/uploading-files-using-the-rest-api-and-client-side-techniques.aspx

    var restURL = appweburl + "/_api/SP.AppContextSite(@target)/web/lists/GetByTitle('DOH%20News%20Drafts')/items(" +

    itemID + ")/AttachmentFiles/add(FileName='" + fileName + "')" +

    "?@target='" + hostweburl + "'" ;

       // use the request executor (cross domain library) to perform the upload

       var reqExecutor = new SP.RequestExecutor(appweburl);


           url: restURL,

           method: "POST",

           headers: {

               "Accept": "application/json; odata=verbose",

               "X-RequestDigest": digest


           contentType: "application/json;odata=verbose",

           binaryStringRequestBody: true,

           body: fileData,

           success: function (x, y, z) {

             //  alert("Success! Your file was uploaded to SharePoint.");


           error: function (x, y, z) {

              // alert("Oooooops… it looks like something went wrong uploading your file.");




  21. Bruno says:

    how would be my url if i want to post the Title name?

  22. Mandar says:

    Great post. Thank. Best solution on .net for uploading documents to SharePoint online using JavaScript

  23. Louren says:

    When I try to  upload a text file this works fine. When uploading a somewhat larger PDF, it get's corrupted. Any idea what's going wrong?

  24. Rama says:

    Hi ,

    Can I build similar application,but browser is IE8. Can you give me some inputs on how to proceed.

    Thanks in advance

  25. Joseph LeMay says:

    For IE8, it does not support the FileReader API, so I'm not sure how you'd use this. I used the built-in attachfile.aspx. Here is some code that works in a napa app. It's up to you to supply this function with the GUID of the list you are attaching to and the itemID of the list item you are attaching to. "readAllAttachments()" is what happens after the file has been uploaded.

    Separately, I have code that checks for support of the FileReader API, so you know when to do this. It's simply

    if(window.FileReader){use the method from this blog post}else{use this method from this comment}

    function fileAttachDialog(){

    //must remove last part of appweburl for this to work.

    var lastPos = appweburl.lastIndexOf("/");

    var attachURL = appweburl.substr(0,lastPos);

    var dialogURL = attachURL + '/_layouts/Attachfile.aspx?ListId={'+ dohNewsGUID +'}&ItemId=' + itemID;

    var options = SP.UI.$create_DialogOptions();

    options.title = "Upload Attachment";

    options.width = 600;

    options.height = 150;

    options.url = dialogURL;

    options.dialogReturnValueCallback = Function.createDelegate(null, CloseCallback);


    function CloseCallback(result, target) {

       if (result == SP.UI.DialogResult.OK) {





  26. Prasad says:

    Thank you very much for this article,  GOD Bless you.

  27. Laurence says:

    Nice work buddy – really appreciated

  28. Michael says:

    Excellent! I've been searching for some time trying to find out how to upload to a subfolder. Very simple! Thanks a lot!

  29. Hareesh says:

    Excellent work.It really helps.

    Thanks for the post

  30. gopal465 says:




  31. Arun says:

    I am trying to upload large files greater than 10MB(Ex: 40 MB) through SharePoint cross domain Rest API calls. I am able to upload files that are upto 10MB using the code below. But when it comes to files that are greater than 10 MB i am getting an error saying Out of memory. Could someone please help me with uploading large files through SharePoint Rest API. Thanks in advance

    Document upload Service call

    var documentUpload = function (librarytitle, foldername, filedata, requestType, success, failure) {

               var deferred = $q.defer();

               var reader = new FileReader();

               reader.onload = function (result) {

                   var fileData = '';

                   var byteArray = new Uint8Array(result.target.result)

                   for (var i = 0; i < byteArray.byteLength; i++) {

                       fileData += String.fromCharCode(byteArray[i])


                if (requestType == "DocumentUpload") {

                       var url = appweburl + "/_api/SP.AppContextSite(@TargetSite)/web/lists/getByTitle(@TargetLibrary)/RootFolder/files/add(url=@TargetFileName,overwrite='true')?" +

                              "@TargetSite='" + hostweburl + "'" +

                              "&@TargetLibrary='" + librarytitle + "'" +

                              "&@TargetFileName='" + filename + "'";


                    // use the request executor (cross domain library) to perform the upload

                   var reqExecutor = new SP.RequestExecutor(appweburl);


                       url: url,

                       method: "POST",

                       headers: {

                           "Accept": "application/json; odata=verbose",

                           "X-RequestDigest": $("#__REQUESTDIGEST").val()


                       contentType: "application/json;odata=verbose",

                       binaryStringRequestBody: true,

                       body: fileData,

                       success: function (data) {

                           //alert("Success! Your file was successfully uploaded to ClientPortal.");

                           var jObject = JSON.parse(data.body)



                       error: function (x, y, z) {






               return deferred.promise;