Uploading multiple files as attachments using chaining of actionfunction in single click.

File operations in salesforce are not easy compared to other technologies because of it's governance limits like maximum heap size, maximum string length etc.This post will be explaining how to upload multiple files with single browse by chaining of actionfunction using JavaScript.

Limitations of apex : inputFile: 

1) apex:inputFile cannot be used in conjunction with an action component, apex:commandButton or apex:commandLink that specifies a rerender or oncomplete attribute. So this tag is not useful on complex vf page.
2)This tag can upload only one file at a time.

Implementation:

In JavaScript function uploadFiles converts attachments body in base-64 encoded string and calls actionFunction saveFileAF(Base64 Encoded attachment body, File Name). In Apex decode base64 string and create attachment. On complete this  again call uploadFiles function in JS for next file. Repeat the same operation for each file.

Code:                                                                                                                                                                                                                                           Visualforce page - AttachmentAF.vfp
<apex:page standardController="Case" extensions="AttachmentActionFunction">
<script type='text/javascript'>
var maxStringSize = 6000000;
var attachmentList;
var j;
function uploadFiles()
{
    input = document.getElementById('fileinput');
    attachmentList = input.files;
    if(j == undefined) 
    j = 0;   
    var file;
    if(j < attachmentList.length)
    {
        file = attachmentList[j];
     var name = file.name;
        var reader = new FileReader();  
        reader.onload = function(e) {  
         var attachmentbodybase64 = window.btoa(reader.result)
            console.log(attachmentbodybase64.length);
            if(attachmentbodybase64.length > maxStringSize )
            alert("File size is too large to handle");
            else
            {
                j++;
                saveFileAF(attachmentbodybase64, name);
            }
        }
         reader.readAsDataURL(file);
    }
    else
    {
        console.log('this is end');
        var url = window.location.origin + '/'+"{!$CurrentPage.parameters.Id}";
        console.log(url);
        window.location.href = url;
    }
    
 }
</script>

<apex:form >
  <input type= "file" Id= "fileinput"  multiple="multiple" />
    <apex:commandButton onclick="uploadFiles(); return false;" value="Upload"/>
    <apex:actionFunction name="saveFileAF" 
         action="{!saveFile}" oncomplete="uploadFiles()" rerender="form"  status="uploading">
        <apex:param name="base64File" value="" assignTo="{!base64}"/>
        <apex:param name="fileName" value="" assignTo="{!fileName}"/>
    </apex:actionFunction>
    <apex:actionStatus id="uploading" >
        <apex:facet name="start" >
            <img src="/img/loading.gif" />                    
  </apex:facet>
 </apex:actionStatus>    
</apex:form>
</apex:page>

                                    Apex Class - Controller : AttachmentActionFunction
public class AttachmentActionFunction {
    public transient String base64;
    public Case c;
    public String getBase64()
    {
        return base64;
    }
    public void setbase64(String base64)
    {
        this.base64 = base64;
    }
    public String fileName {get; set;}
    public AttachmentActionFunction(ApexPages.StandardController std)
    {
        c = (Case)std.getRecord();
    }
    public void saveFile()
    {
        Attachment a = new Attachment(parentId = c.Id, Body =  EncodingUtil.base64Decode(base64), name = fileName);
        insert a;
    }
}


Create a new button on case use content source as AttachmentAF Visualforce page. Expose this button on case page layout.

Limitations of this way:

Maximum allowed String length in Salesforce is 6000000 characters. We are converting attachment body in base64 encoded string. Which Limits to have an attachment of size 4.3 MB max.


Comments

  1. But we are not able to view those attachment once uploaded to a parent id
    Please give us a solution

    ReplyDelete
    Replies
    1. Update this line

      from

      var attachmentbodybase64 = window.btoa(reader.result)

      to
      var attachmentbodybase64 = reader.result.split('base64,')[1];

      Delete

Post a Comment

Popular posts from this blog

Dynamic Visualforce Bindings with Example

Two Columns Multi-Select Picklist Lightning Component