Javascript – SharePoint Online REST – Image upload via JavaScript/AJAX

javascriptrestsharepointsharepoint-online

I'm trying to upload an image to SharePoint using native JavaScript/jQuery – NOT SP.RequestExecutor.

I've cracked the authentication issue, nice and easy, so now it's just a case of working out how to upload binary files. If I put plain text in the file, it uploads fine, it's just binary data I'm having trouble with.

My code so far is included below. getToken() does it's thing and leaves me with a valid digest object to use. Also note I've blanked out the document library name with *'s.

function PerformUpload(fileName, fileData) {    
    getToken();
    $.ajax({
        url: siteFullUrl +
        "/_api/web/GetFolderByServerRelativeUrl('/*****/')/Files" +
        "/Add(url='" + fileName + "', overwrite=true)",
        type: "POST",
        async: false,
        data: fileData,
        processData: false,
        contentType: "application/json;odata=verbose",
        headers: {
            "Accept": "application/json;odata=verbose",
            "X-RequestDigest": digest
        },
        success: function (data) {
            alert("Success");
        },
        error: function (err) {
            alert("Error: \r\n" + JSON.stringify(err));
        }
    });
}

I've tried many combinations of different values for contentType, setting binaryStringRequestBody: true but the image is still corrupt when it comes into SharePoint.

My code at the moment to parse the file into binary is

var reader = new FileReader();
reader.onload = function (result) {
    var fileName = '',
     libraryName = '',
     fileData = '';

    var byteArray = new Uint8Array(result.target.result)
    for (var i = 0; i < byteArray.byteLength; i++) {
        fileData += String.fromCharCode(byteArray[i])
    }
    PerformUpload("image.jpg", fileData);
};
reader.readAsArrayBuffer(fileInput);

A file is being uploaded to SharePoint but if I try and view or download it it's corrupt.

Can anyone provide any guidance as to the correct way to upload a binary file to SharePoint? I should mention that if I replace (on the ajax call) data: fileData, with data: "A simple string", the file uploads and when I download it the contents of the file are A simple string.

Best Answer

If you are using SP.RequestExecutor to upload the file to SharePoint, you must be converted the ArrayBuffer into a string which can then be set as the body of a POST operation. See details here which guide you how to Upload file to SharePoint using REST by SP.RequestExecutor.

If you are using parsed file into binary with Jquery.Ajax, the image will corrupt when it comes into SharePoint. Also noted that the FileReader object accepts the file information for loading asynchronously. The onload and onerror events fire when the file is loaded successfully or fails. We should keep the proccess of onload event by default and get the result in onloadend event.

I tried the following articles and it work:

How to: Upload a file by using the REST API and jQuery

For simple, here is how I implemented:

var fileInput = jQuery('#getFile');
var file = fileInput[0].files[0];
var serverRelativeUrlToFolder = '*****'; //if the library in subsite, You have to remove the forward slash "/" before the document library relative url. 
proccessUploadUsingJQueryAjax(file, serverRelativeUrlToFolder);

function getFileBuffer(file) {
     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(file);
     return deferred.promise();
}
function addFileToFolderUsingJQueryAjax(fileName, arrayBuffer, serverRelativeUrlToFolder) {
       // Construct the endpoint.
        var fileCollectionEndpoint = String.format(
                "{0}/_api/web/GetFolderByServerRelativeUrl('{1}')/files/add(overwrite=true, url='{2}')",
                _spPageContextInfo.webAbsoluteUrl, 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,
            contentType: "application/json;odata=verbose",
            headers: {
                "accept": "application/json;odata=verbose",
                "X-RequestDigest": jQuery("#__REQUESTDIGEST").val()
            }
        });
    }
function proccessUploadUsingJQueryAjax(file, serverRelativeUrlToFolder){
     var getFile = getFileBuffer(file);
     getFile.done(function (arrayBuffer) {
     // Add the file to the SharePoint folder.
            var addFile = addFileToFolderUsingJQueryAjax("image.jpg", arrayBuffer, serverRelativeUrlToFolder);
            addFile.done(function (file, status, xhr) {
                alert("File Uploaded");
            });
            addFile.fail(function (error) { alert("Error Add File: " + error.responseText); });
        });
     getFile.fail(function (error) { alert("Error Get File: " + error.responseText); });
}

Please let me know if it solved your problem.

Related Topic