Upload a file by using the REST API and jQuery

The code examples in this article use the REST interface and jQuery AJAX requests to add a local file to the Documents library, and then change properties of the list item that represents the uploaded file.

This process uses the following high-level steps:

  1. Convert the local file to an array buffer by using the FileReader API, which requires HTML5 support. The jQuery(document).ready function checks for FileReader API support in the browser.

  2. Add the file to the Shared Documents folder by using the Add method on the folder's file collection. The array buffer is passed in the body of the POST request.

    These examples use the getfolderbyserverrelativeurl endpoint to reach the file collection, but you can also use a list endpoint (example: https://{site_url}/_api/web/lists/getbytitle('{list_title}')/rootfolder/files/add).

  3. Get the list item that corresponds to the uploaded file by using the ListItemAllFields property of the uploaded file.

  4. Change the display name and title of the list item by using a MERGE request.

Running the code examples

Both code examples in this article use the REST API and jQuery AJAX requests to upload a file to the Shared Documents folder and then change list item properties.

The first example uses SP.AppContextSite to make calls across SharePoint domains, like a SharePoint-hosted add-in would do when uploading files to the host web.

The second example makes same-domain calls, like a SharePoint-hosted add-in would do when uploading files to the add-in web, or a solution that's running on the server would do when uploading files.

Note

Provider-hosted add-ins written in JavaScript must use the SP.RequestExecutor cross-domain library to send requests to a SharePoint domain. For an example, see upload a file by using the cross-domain library.

To use the examples in this article, you'll need the following:

  • SharePoint Server or SharePoint Online.

  • Write permissions to the Documents library for the user running the code. If you're developing a SharePoint Add-in, you can specify Write add-in permissions at the List scope.

  • Browser support for the FileReader API (HTML5).

  • A reference to the jQuery library in your page markup. For example:

    <script src="https://ajax.aspnetcdn.com/ajax/jQuery/jquery-1.9.1.min.js" type="text/javascript"></script>
    
  • The following controls in your page markup.

    <input id="getFile" type="file"/><br />
    <input id="displayName" type="text" value="Enter a unique name" /><br />
    <input id="addFileButton" type="button" value="Upload" onclick="uploadFile()"/>
    

Code example 1: Upload a file across SharePoint domains by using the REST API and jQuery

The following code example uses the SharePoint REST API and jQuery AJAX requests to upload a file to the Documents library and to change properties of the list item that represents the file. The context for this example is a SharePoint-hosted add-in that uploads a file to a folder on the host web.

Note

You need to meet the requirements listed in the section Running the code examples to use this example.

'use strict';

var appWebUrl, hostWebUrl;

jQuery(document).ready(function () {
  // Check for FileReader API (HTML5) support.
  if (!window.FileReader) {
    alert('This browser does not support the FileReader API.');
  }

  // Get the add-in web and host web URLs.
  appWebUrl = decodeURIComponent(getQueryStringParameter("SPAppWebUrl"));
  hostWebUrl = decodeURIComponent(getQueryStringParameter("SPHostUrl"));
});

// Upload the file.
// You can upload files up to 2 GB with the REST API.
function uploadFile() {
  // Define the folder path for this example.
  var serverRelativeUrlToFolder = 'shared documents';

  // Get test values from the file input and text input page controls.
  // The display name must be unique every time you run the example.
  var fileInput = jQuery('#getFile');
  var newName = jQuery('#displayName').val();

  // Initiate method calls using jQuery promises.
  // Get the local file as an array buffer.
  var getFile = getFileBuffer();

  getFile.done(function (arrayBuffer) {
    // Add the file to the SharePoint folder.
    var addFile = addFileToFolder(arrayBuffer);
    addFile.done(function (file, status, xhr) {
      // Get the list item that corresponds to the uploaded file.
      var getItem = getListItem(file.d.ListItemAllFields.__deferred.uri);
      getItem.done(function (listItem, status, xhr) {
        // Change the display name and title of the list item.
        var changeItem = updateListItem(listItem.d.__metadata);
        changeItem.done(function (data, status, xhr) {
          alert('file uploaded and updated');
        });
        changeItem.fail(onError);
      });
      getItem.fail(onError);
    });
    addFile.fail(onError);
  });

  getFile.fail(onError);

  // Get the local file as an array buffer.
  function getFileBuffer() {
    var deferred = jQuery.Deferred();
    var reader = new FileReader();
    reader.onloadend = function (e) {
      deferred.resolve(e.target.result);
    }
    reader.onerror = function (e) {
      deferred.reject(e.target.error);
    }
    reader.readAsArrayBuffer(fileInput[0].files[0]);
    return deferred.promise();
  }

  // Add the file to the file collection in the Shared Documents folder.
  function addFileToFolder(arrayBuffer) {
    // Get the file name from the file input control on the page.
    var parts = fileInput[0].value.split('\\');
    var fileName = parts[parts.length - 1];

    // Construct the endpoint.
    var fileCollectionEndpoint = String.format(
        "{0}/_api/sp.appcontextsite(@target)/web/getfolderbyserverrelativeurl('{1}')/files" +
        "/add(overwrite=true, url='{2}')?@target='{3}'",
        appWebUrl, serverRelativeUrlToFolder, fileName, hostWebUrl);

    // Send the request and return the response.
    // This call returns the SharePoint file.
    return jQuery.ajax({
      url: fileCollectionEndpoint,
      type: "POST",
      data: arrayBuffer,
      processData: false,
      headers: {
        "accept": "application/json;odata=verbose",
        "X-RequestDigest": jQuery("#__REQUESTDIGEST").val(),
        "content-length": arrayBuffer.byteLength
      }
    });
  }

  // Get the list item that corresponds to the file by calling the file's ListItemAllFields property.
  function getListItem(fileListItemUri) {
    // Construct the endpoint.
    // The list item URI uses the host web, but the cross-domain call is sent to the
    // add-in web and specifies the host web as the context site.
    fileListItemUri = fileListItemUri.replace(hostWebUrl, '{0}');
    fileListItemUri = fileListItemUri.replace('_api/Web', '_api/sp.appcontextsite(@target)/web');

    var listItemAllFieldsEndpoint = String.format(fileListItemUri + "?@target='{1}'", appWebUrl, hostWebUrl);

    // Send the request and return the response.
    return jQuery.ajax({
      url: listItemAllFieldsEndpoint,
      type: "GET",
      headers: { "accept": "application/json;odata=verbose" }
    });
  }

  // Change the display name and title of the list item.
  function updateListItem(itemMetadata) {
    // Construct the endpoint.
    // Specify the host web as the context site.
    var listItemUri = itemMetadata.uri.replace('_api/Web', '_api/sp.appcontextsite(@target)/web');
    var listItemEndpoint = String.format(listItemUri + "?@target='{0}'", hostWebUrl);

    // Define the list item changes. Use the FileLeafRef property to change the display name.
    // For simplicity, also use the name as the title.
    // The example gets the list item type from the item's metadata, but you can also get it from the
    // ListItemEntityTypeFullName property of the list.
    var body = String.format("{{'__metadata':{{'type':'{0}'}},'FileLeafRef':'{1}','Title':'{2}'}}",
        itemMetadata.type, newName, newName);

    // Send the request and return the promise.
    // This call does not return response content from the server.
    return jQuery.ajax({
      url: listItemEndpoint,
      type: "POST",
      data: body,
      headers: {
        "X-RequestDigest": jQuery("#__REQUESTDIGEST").val(),
        "content-type": "application/json;odata=verbose",
        "content-length": body.length,
        "IF-MATCH": itemMetadata.etag,
        "X-HTTP-Method": "MERGE"
      }
    });
  }
}

// Display error messages.
function onError(error) {
  alert(error.responseText);
}

// Get parameters from the query string.
// For production purposes you may want to use a library to handle the query string.
function getQueryStringParameter(paramToRetrieve) {
  var params = document.URL.split("?")[1].split("&amp;");
  for (var i = 0; i < params.length; i = i + 1) {
    var singleParam = params[i].split("=");
    if (singleParam[0] == paramToRetrieve) return singleParam[1];
  }
}

Code example 2: Upload a file in the same domain by using the REST API and jQuery

The following code example uses the SharePoint REST API and jQuery AJAX requests to upload a file to the Documents library and to change properties of the list item that represents the file. The context for this example is a solution that's running on the server. The code would be similar in a SharePoint-hosted add-in that uploads files to the add-in web.

Note

You need to meet the requirements listed in the section Running the code examples to use this example.

'use strict';

jQuery(document).ready(function () {
  // Check for FileReader API (HTML5) support.
  if (!window.FileReader) {
    alert('This browser does not support the FileReader API.');
  }
});

// Upload the file.
// You can upload files up to 2 GB with the REST API.
function uploadFile() {
  // Define the folder path for this example.
  var serverRelativeUrlToFolder = '/shared documents';

  // Get test values from the file input and text input page controls.
  var fileInput = jQuery('#getFile');
  var newName = jQuery('#displayName').val();

  // Get the server URL.
  var serverUrl = _spPageContextInfo.webAbsoluteUrl;

  // Initiate method calls using jQuery promises.
  // Get the local file as an array buffer.
  var getFile = getFileBuffer();
  getFile.done(function (arrayBuffer) {
    // Add the file to the SharePoint folder.
    var addFile = addFileToFolder(arrayBuffer);
    addFile.done(function (file, status, xhr) {
      // Get the list item that corresponds to the uploaded file.
      var getItem = getListItem(file.d.ListItemAllFields.__deferred.uri);
      getItem.done(function (listItem, status, xhr) {
        // Change the display name and title of the list item.
        var changeItem = updateListItem(listItem.d.__metadata);
        changeItem.done(function (data, status, xhr) {
          alert('file uploaded and updated');
        });
        changeItem.fail(onError);
      });
      getItem.fail(onError);
    });
    addFile.fail(onError);
  });
  getFile.fail(onError);

  // Get the local file as an array buffer.
  function getFileBuffer() {
    var deferred = jQuery.Deferred();
    var reader = new FileReader();
    reader.onloadend = function (e) {
      deferred.resolve(e.target.result);
    }
    reader.onerror = function (e) {
      deferred.reject(e.target.error);
    }
    reader.readAsArrayBuffer(fileInput[0].files[0]);
    return deferred.promise();
  }

  // Add the file to the file collection in the Shared Documents folder.
  function addFileToFolder(arrayBuffer) {
    // Get the file name from the file input control on the page.
    var parts = fileInput[0].value.split('\\');
    var fileName = parts[parts.length - 1];

    // Construct the endpoint.
    var fileCollectionEndpoint = String.format(
            "{0}/_api/web/getfolderbyserverrelativeurl('{1}')/files" +
            "/add(overwrite=true, url='{2}')",
            serverUrl, serverRelativeUrlToFolder, fileName);

    // Send the request and return the response.
    // This call returns the SharePoint file.
    return jQuery.ajax({
        url: fileCollectionEndpoint,
        type: "POST",
        data: arrayBuffer,
        processData: false,
        headers: {
          "accept": "application/json;odata=verbose",
          "X-RequestDigest": jQuery("#__REQUESTDIGEST").val(),
          "content-length": arrayBuffer.byteLength
        }
    });
  }

  // Get the list item that corresponds to the file by calling the file's ListItemAllFields property.
  function getListItem(fileListItemUri) {
    // Send the request and return the response.
    return jQuery.ajax({
      url: fileListItemUri,
      type: "GET",
      headers: { "accept": "application/json;odata=verbose" }
    });
  }

  // Change the display name and title of the list item.
  function updateListItem(itemMetadata) {
    // Define the list item changes. Use the FileLeafRef property to change the display name.
    // For simplicity, also use the name as the title.
    // The example gets the list item type from the item's metadata, but you can also get it from the
    // ListItemEntityTypeFullName property of the list.
    var body = String.format("{{'__metadata':{{'type':'{0}'}},'FileLeafRef':'{1}','Title':'{2}'}}",
        itemMetadata.type, newName, newName);

    // Send the request and return the promise.
    // This call does not return response content from the server.
    return jQuery.ajax({
        url: itemMetadata.uri,
        type: "POST",
        data: body,
        headers: {
          "X-RequestDigest": jQuery("#__REQUESTDIGEST").val(),
          "content-type": "application/json;odata=verbose",
          "content-length": body.length,
          "IF-MATCH": itemMetadata.etag,
          "X-HTTP-Method": "MERGE"
        }
    });
  }
}

// Display error messages.
function onError(error) {
  alert(error.responseText);
}

See also