Uploading multiple attachments in SharePoint with one Input 1

misc3_bgI ran into the problem of not being able to upload an indefinite number of attachments to a SharePoint list item.  Using a file input could only upload file per input and I needed to allow the user to upload as many as they wanted.  I ended up following this blog post.

To select multiple files in one file input, the JavaScript plugin jquery.multifile.js is needed.  With this plugin, all you need to do to select multiple files is include multiple=”multiple” and class=”multi” on the file input.  When you choose a file it shows up below the input like this:

multifile.js

This plugin does not handle uploading the files to SharePoint, it just allows the user to select more than one file.  To upload the files these functions were created:

To get an array of all the files:
*txtAttachments and “Change Orders” are specific to the input id and list name I used

function AddAllAttachments(id){
  var data = [];
  var fileArray = [];
  $("#txtAttachements input:file").each(function () {
    if ($(this)[0].files[0]) {
      fileArray.push({ "Attachment": $(this)[0].files[0] });
    }
  });
  data.push({"Files": fileArray});
  createItemWithAttachments("Change Orders", data, id).then(
    function(){
      console.log('Item created with Multiple attachments');
    },
    function(sender, args){
      console.log('Error occured' + args.get_message());
    }
  );
}

Once the files have been added to the array this function gets the item that the files are going to be added to and then passes them on to be uploaded:

  var createItemWithAttachments = function(listName, listValues, id){
  var fileCountCheck = 0;
  var fileNames;
  var context = new SP.ClientContext.get_current();
  var dfd = $.Deferred();
  var targetList = context.get_web().get_lists().getByTitle(listName);
  context.load(targetList);
  var itemCreateInfo = new SP.ListItemCreationInformation();
  context.executeQueryAsync(
    function () {
      if (listValues[0].Files.length !== 0) {
        if (fileCountCheck <= listValues[0].Files.length - 1) {
          loopFileUpload(listName, id, listValues, fileCountCheck).then(
            function () {
            },
            function (sender, args) {
              console.log("Error uploading");
              dfd.reject(sender, args);
            }
          );
        }
      } else {
         dfd.resolve(fileCountCheck);
      }
    },
    function(sender, args){
       console.log('Error occured' + args.get_message());
    });
  return dfd.promise();
};

This function loops through each file and uploads them one by one

function loopFileUpload(listName, id, listValues, fileCountCheck) {
  var dfd = $.Deferred();
  uploadFile(listName, id, listValues[0].Files[fileCountCheck].Attachment).then(
    function (data) {
      var objcontext = new SP.ClientContext();
      var targetList = objcontext.get_web().get_lists().getByTitle(listName);
      var listItem = targetList.getItemById(id);
      objcontext.load(listItem);
      objcontext.executeQueryAsync(function () {
        console.log("Reload List Item- Success");
        fileCountCheck++;
        if (fileCountCheck <= listValues[0].Files.length - 1) {
          loopFileUpload(listName, id, listValues, fileCountCheck);
        } else {
          console.log(fileCountCheck + ": Files uploaded");
        }
      },
      function (sender, args) {
        console.log("Reload List Item- Fail" + args.get_message());
      });
    },
    function (sender, args) {
      console.log("Not uploaded");
      dfd.reject(sender, args);
    }
  );
  return dfd.promise();
}

By calling this function:

function uploadFile(listName, id, file) {
  var deferred = $.Deferred();
  var fileName = file.name;
  getFileBuffer(file).then(
    function (buffer) {
      var bytes = new Uint8Array(buffer);
      var binary = '';
      for (var b = 0; b < bytes.length; b++) {
        binary += String.fromCharCode(bytes[b]);
      }
      console.log(' File size:' + bytes.length);
      $.getScript("http://enerfabsp2013:1000/_layouts/15/SP.RequestExecutor.js", function () {
        var createitem = new SP.RequestExecutor(_spPageContextInfo.webServerRelativeUrl);
        createitem.executeAsync({
          url: _spPageContextInfo.webServerRelativeUrl + "/_api/web/lists/GetByTitle('" + listName + "')/items(" + id + ")/AttachmentFiles/add(FileName='" + file.name + "')",
          method: "POST",
          binaryStringRequestBody: true,
          body: binary,
          success: fsucc,
          error: ferr,
          state: "Update"
        });
        function fsucc(data) {
          console.log(data + ' uploaded successfully');
          deferred.resolve(data);
        }
        function ferr(data) {
          console.log(fileName + "not uploaded error");
          deferred.reject(data);
        }
      });
    },
    function (err) {
      deferred.reject(err);
    }
  );
  return deferred.promise();
}

Finally, this is the function used to actually read the files on the page

function getFileBuffer(file) {
  var deferred = $.Deferred();
  var reader = new FileReader();
  reader.onload = function (e) {
    deferred.resolve(e.target.result);
  };
  reader.onerror = function (e) {
    deferred.reject(e.target.error);
  };
  reader.readAsArrayBuffer(file);
  return deferred.promise();
}

One comment

  1. Hi,

    I tried uploading .pptx file. Got Error

    Failed to execute ‘readAsArrayBuffer’ on ‘FileReader’: parameter 1 is not of type ‘Blob’.

    Like

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s