Monday, May 15, 2017

Upload attachment on Salesforce without having heap size limit exceeded

Have you ever had a form for uploading attachments on your Visualforce page but had to restrict it to file size limit so as not to exceed Salesforce heap size governor limit?

Well this limit can be override to a maximum of 25 megabytes instead of around 3 megabytes using apex controller. It also support multiple upload at once.

Here is how I have achieved it.
Integrate the following code to your visualforce page. Basically to just need to replace the variable 'PARENT_ID' and maybe change the listener of the 'input' if yours have a different selector. 


Document of size 9 mb has been uploaded.


Attachment being created on the Contact record.


Hope it helps. Cheers!!
``` html
<apex:page >
    <apex:includeScript value="https://code.jquery.com/jquery-2.2.4.js"/>
    <script>
    jQuery(document).ready(function($) {
        $('input').on('change', function(e){
            for (var i = 0; i < this.files.length; i++) {
                uploading += 1;
                upload_file(this.files[i], PARENT_ID, function(err, res){ //pass the parentId here
                    if (uploading === uploaded){
                        console.log('uploaded'); //your operation once finish
                    }
                })
            }
        });
        var uploading = 0;
        var uploaded = 0;
        var upload_file = function(file, parentId, callback) {
            filetoBase64(file, function(err, content){
                var attachment_object = {
                    parentId: parentId,
                    Body: content,
                    Name: file.name,
                    ContentType: file.type
                };
                $.ajax({
                    url: '/services/data/v38.0/sobjects/Attachment',
                    data: JSON.stringify(attachment_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) {
                                var percentComplete = evt.loaded / evt.total;
                                //Do something with upload progress
                            }
                        }, false);
                        return xhr;
                    },
                    success: function(response) {
                        uploaded += 1;
                        console.log(response); // the id of the attachment
                        callback(null, true)
                    }
                });
            })
        }
     
        var filetoBase64 = function(file, callback){
            var reader = new FileReader();
            reader.onload = function() {
                var fileContents = reader.result;
                var base64Mark = 'base64,';
                var dataStart = fileContents.indexOf(base64Mark) + base64Mark.length;
                fileContents = fileContents.substring(dataStart);
                callback(null, fileContents);
            }
            reader.readAsDataURL(file);
        }
    });
    </script>
    <input type="file" multiple="multiple"/>
</apex:page>
```

2 comments:

  1. Hi

    This is not working on communities. ANy work around for that?

    ReplyDelete
  2. Hi Can This work when Uploaded from Sites?

    ReplyDelete