A little over eight months ago I wrote a very brief post about using SPServices to add attachments to a SharePoint list. Full credit here goes to Brendan Wilbore who wrote the blog post that I linked to.
There was a problem, though – the solution relies on the fileReader JavaScript feature which requires Internet Explorer 10, and the default browser deployed within my organization is Internet Explorer 9. What we need is a fileReader alternative for older browsers. Thankfully, such a thing exists. Today I’m going to post some example code that uses the fileReader polyfill and works in older browsers.
What You Need
The code has several pre-requisites. You’ll need jQuery, jQuery UI, SPServices, SWFObject and the JavaScript and flash file that form the fileReader polyfill.
For the purposes of my demo I created a simple SharePoint list called “File Attachment Test.” The list has a single field – title – and attachments to the list are enabled. Your list is probably named differently, so you’ll need to change the references in the code to reflect your list name.
The Code
<html> <head> <meta charset="utf-8" /> <title>File Attachment Test</title> http://ajax.googleapis.com/ajax/libs/jquery/1.11.1/jquery.min.js http://ajax.googleapis.com/ajax/libs/jqueryui/1.10.4/jquery-ui.min.js http://ajax.googleapis.com/ajax/libs/swfobject/2.2/swfobject.js http://js/jquery.FileReader.min.js http://js/jquery.SPServices-2013.01.min.js var selectedfile = false; $(document).ready(function() { $('input#itemfile').fileReader({filereader: 'js/filereader.swf'}); $('input#itemfile').change(function(e) { selectedfile = e.target.files[0]; $('span#filename').html(selectedfile.name); $('span#fileinput').hide(); }); $('input#createitem').click(function() { $().SPServices({ operation: 'UpdateListItems', async: false, listName: 'File Attachment Test', batchCmd: 'New', webURL: '/demo', valuepairs: [ ['Title', $('input#itemtitle').val()] ], completefunc: function(xData, Status) { if (Status == 'success' && $(xData.responseXML).find('ErrorCode').text() == '0x00000000') { currentitem = $(xData.responseXML).SPFilterNode("z:row").attr("ows_ID"); alert('List item created with ID ' + currentitem); if (selectedfile) { filereader = new FileReader(); filereader.filename = selectedfile.name; filereader.onload = function() { data = filereader.result; n = data.indexOf(';base64,') + 8; data = data.substring(n); $().SPServices({ operation: 'AddAttachment', async: false, listName: 'File Attachment Test', listItemID: currentitem, fileName: selectedfile.name, attachment: data, completefunc: function(xData, Status) { alert('File uploaded'); } }); }; filereader.onabort = function() { alert('Upload aborted'); }; filereader.onerror = function() { alert('Upload error'); }; filereader.readAsDataURL(selectedfile); } } else alert('List item creation failed'); } }) }); }); </head> <body> <p>Title:<br><input type="text" id="itemtitle"></p> <p>File:<br><span id="fileinput"><input type="file" id="itemfile"></span><span id="filename"></span></p> <p><input type="button" id="createitem" value="Go!"></p> </body> </html>
Notes
The fileReader polyfill takes the file input box and puts the flash file on top of it, so that the file selection and upload is handled by flash instead of natively in the browser. I found that this fell apart of the file input box didn’t remain in the same place on the page. In other words, I had problems if I tried to use jQuery’s .show() and .hide() functions (or similar).
I solved this by putting the file selection form in a pop-up window. If the page you place your form on is static (i.e. nothing changes after the DOM is loaded) then you shouldn’t have this problem.
Enjoy!