Upload multiple files through Visualforce page



While uploading the multiple files at the same time you may have faced the problem like ‘View state size limit exceeded’, ‘Heap size’ limit and file size limit. To overcome these limits we can use javascript to handle the file uploading through the Visualforce page.

I have also faced the problem like View state size limit exceeded and Heap size limit, to solve the issue I decided to send/upload the files using HTTP POST Request with the help of Ajax, Jquery, javascript. Below is the code snippet for uploading files in the ContentVersion object.

<apex:slds />
<apex:includeScript value="https://code.jquery.com/jquery-2.2.4.js"/&gt;
//function starts
var fileLenght=0;
$('#uploadBtn').click(function() {
var v=document.getElementById('addr');
fileLenght = v.files.length;
for (var i = 0; i < v.files.length; i++) {
uploadSelectedFile(v.files[i], function(err, res){
FileUploading += 1;
if (FileUploading === FileUploaded){
alert('upload completed');
//blank input file value
document.getElementById("addr").value = "";
var FileUploading = 0;
var FileUploaded = 0;
var ids = new Array();
var uploadSelectedFile = function(file, callback) {
filetoBase64(file, function(err, content){
var conVer_object = {
ContentLocation : 'S',
VersionData : content,
PathOnClient : file.name,
Title : file.name
url: '/services/data/v39.0/sobjects/ContentVersion',
data: JSON.stringify(conVer_object ),
type: 'POST',
processData: false,
contentType: false,
headers: {'Authorization': 'Bearer {!$Api.Session_ID}', 'Content-Type': 'application/json'},
xhr: function(){
var xhr = new window.XMLHttpRequest();
//Upload progress
xhr.upload.addEventListener("progress", function(evt){
if (evt.lengthComputable) {
$('#progress_bar_container').css('display', 'block');
var percentComplete = evt.loaded / evt.total;
console.log('percentComplete '+percentComplete );
var percentCompletex= percentComplete*100;
$('#percentText').html("Uploading. Please wait... "+Math.round(percentCompletex)+"%");
$('.progress').css('width', percentCompletex+ "%");
if(percentCompletex == 100){
$('#progress_bar_container').css('display', 'none');
}, false);
return xhr;
success: function(response) {
FileUploaded += 1;
console.log(response.id); // the id of the attachment
console.log('Ids: ' +ids);
$('#records').html('File has been uploeded. Uploaded File ids: ' +ids);
if(fileLenght == FileUploaded ){
callback(null, true)
//Read file
var filetoBase64 = function(file, callback){
var reader = new FileReader();
reader.onload = function() {
var myFileContents = reader.result;
var base64Mark = 'base64,';
var dataStart = myFileContents.indexOf(base64Mark) + base64Mark.length;
myFileContents = myFileContents.substring(dataStart);
callback(null, myFileContents);
.slds-scope .slds-page-header{
border-radius: 0px;
box-shadow: 0 0px 0px 0 rgba(0, 0, 0, 0.1);
<apex:form >
<div class="slds" style="border:1px solid #D9D9D9;">
<div class="slds-page-header">
<span style=""> Upload Files</span>
<div id="progress_bar_container" style="display:none; padding:10px;">
<span id="percentText"></span>
<div class="slds-progress-bar" aria-valuemin="0" aria-valuemax="100" aria-valuenow="25" role="progressbar">
<span class="slds-progress-bar__value progress" style=" width: 0%;">
<span class="slds-assistive-text">Progress: 25%</span>
<div class="bodyPart">
Select file: <input type="file" name="files[]" multiple="multiple" id="addr"/>
<input type="button" id="uploadBtn" name="Address" value="Upload" class="slds-button slds-button--brand"></input>
<div id="uploadedrec" style="padding:10px;">
<span id="records" style=" color:green; ">
view raw UploadFiles hosted with ❤ by GitHub

On ‘Upload’ button click this method will be called. Here ‘#uploadBtn’ is the id of the button.

$(‘#uploadBtn’).click(function() { …}
If the user selects multiple files, Iterating over files length.

for (var i = 0; i < v.files.length; i++) { … }
In every iteration uploadSelectedFile, JS function will be called.

uploadSelectedFile(v.files[i], function(err, res){ …}
Reading the files and converted into the base64 format.

filetoBase64(file, function(err, content){ }
ContentVersion object variable with required fields.

var conVer_object = {
ContentLocation : ‘S’,
VersionData : content, // File body
PathOnClient : file.name, // File name
Title : file.name //File title
This AJAX method used to perform the asynchronous HTTP request to Salesforce.

$.ajax({ … }
URL or Endpoint: HTTP POST method will post the content to the specified location (ContentVersion object).

url: ‘/services/data/v39.0/sobjects/ContentVersion’,
Header: Salesforce Session_ID used for authentication.

headers: {‘Authorization’: ‘Bearer {!$Api.Session_ID}’, ‘Content-Type’: ‘application/json’},
XML HttpRequest object: Send the data from page to server (Salesforce) in the background.

var xhr = new window.XMLHttpRequest();

The addEventListener function listen to the progress of uploading.

xhr.upload.addEventListener(“progress”, function(evt){ … }
These lines of code will display the Progress bar on the page.

$(‘#progress_bar_container’).css(‘display’, ‘block’);
var percentComplete = evt.loaded / evt.total;
console.log(‘percentComplete ‘+percentComplete );
var percentCompletex= percentComplete*100;
$(‘#percentText’).html(“Uploading. Please wait… “+Math.round(percentCompletex)+”%”);
$(‘.progress’).css(‘width’, percentCompletex+ “%”);
if(percentCompletex == 100){
$(‘#progress_bar_container’).css(‘display’, ‘none’);

This success function will return the success message with the ids of the file that just uploaded.






XML Http Request

AJAX Method


Hope this blog post will help many.

Happy coding…

Arun Kumar

Arun Kumar is a Salesforce Certified Platform Developer I with over 7+ years of experience working on the Salesforce platform. He specializes in developing custom applications, integrations, and reports to help customers streamline their business processes. Arun is passionate about helping businesses leverage the power of Salesforce to achieve their goals.

This Post Has One Comment

  1. Ravi Shah

    Nice Article.
    I have one question, If we use the same thing for salesforce community user it’s not working.

Leave a Reply