upload file using lightning sfdmconkey

Custom File Upload In Salesforce Lightning Component – Upload Large Attachments

Lightning Component

Hey Guys,

Today in this post we are going to learn about how to create a custom file upload salesforce lightning component. This post inspire and new updated version of ‘Peter Knolle‘ post ‘upload file component’.

For this post we are using the chunk file upload method, by this chunk file upload method we can upload large file attachments within the heap size limitation, we are using the small 750kb chunks for upload our attachment.

Using this sample code you can upload attachments upto 4.5 Mb.
Lightning Component Output Sample : 

upload file using lightning sfdmconkey

Now let’s start code …

Step 1 : Create Apex Controller : FileUploadController.apxc

From Developer Console >> File >> New >> Apex Class

/*
 * sfdcmonkey.com 
 * 25/9/2017
 */
public with sharing class FileUploadController {


    @AuraEnabled
    public static Id saveChunk(Id parentId, String fileName, String base64Data, String contentType, String fileId) {
        // check if fileId id ''(Always blank in first chunk), then call the saveTheFile method,
        //  which is save the check data and return the attachemnt Id after insert, 
        //  next time (in else) we are call the appentTOFile() method
        //   for update the attachment with reamins chunks   
        if (fileId == '') {
            fileId = saveTheFile(parentId, fileName, base64Data, contentType);
        } else {
            appendToFile(fileId, base64Data);
        }

        return Id.valueOf(fileId);
    }

    public static Id saveTheFile(Id parentId, String fileName, String base64Data, String contentType) {
        base64Data = EncodingUtil.urlDecode(base64Data, 'UTF-8');

        Attachment oAttachment = new Attachment();
        oAttachment.parentId = parentId;

        oAttachment.Body = EncodingUtil.base64Decode(base64Data);
        oAttachment.Name = fileName;
        oAttachment.ContentType = contentType;

        insert oAttachment;

        return oAttachment.Id;
    }

    private static void appendToFile(Id fileId, String base64Data) {
        base64Data = EncodingUtil.urlDecode(base64Data, 'UTF-8');

        Attachment a = [
            SELECT Id, Body
            FROM Attachment
            WHERE Id =: fileId
        ];

        String existingBody = EncodingUtil.base64Encode(a.Body);

        a.Body = EncodingUtil.base64Decode(existingBody + base64Data);

        update a;
    }
}
  • see code comments.
Step 2 : Create Lightning Component: fileUpload.cmp 

From Developer Console >> File >> New >> Lightning Component

<!-- 
   * sfdcmonkey.com/ Piyush Soni 
   * Date : 25/9/2017
   * Locker Service Ready.
   -->
<aura:component controller="FileUploadController">
 <!-- 'parentId' Aura Attribute for store the Id for Parent Record where we are attach our file -->  
   <aura:attribute name="parentId" type="Id" default="0016F000024nYzwQAE" />
 <!-- 'showLoadingSpinner' attribute for show/hide the uploading image and msg in aura:if-->
   <aura:attribute name="showLoadingSpinner" type="boolean" default="false" />
 <!-- 'fileName' attribute for display the selected file name -->  
   <aura:attribute name="fileName" type="String" default="No File Selected.." />
 <!-- Lightning Input with file type and on file change call the 'handleFilesChange' controller --> 
 
   <lightning:input aura:id="fileId" onchange="{!c.handleFilesChange}" type="file" name="file" label="Upload Attachment" multiple="false"/>
   <div class="slds-text-body_small slds-text-color_error">{!v.fileName} </div>
 
 <!--use aura:if for show-hide the loading spinner image--> 
   <aura:if isTrue="{!v.showLoadingSpinner}">
      <div class="slds-text-body_small slds-text-color_error">Uploading... 
         <img src="/auraFW/resources/aura/images/spinner.gif" class="spinner-img" alt="Loading"/>'
      </div>
   </aura:if>
   
 <br/>

   <button class="slds-button slds-button_brand" onclick="{!c.doSave}">Upload Attachment</button>
</aura:component>
  • In the above lightning component on line number 10, we have a attribute called ‘parentId’ , in this attribute you have need to set the parent id, in in sample i am using the account id.
  • see code comments.

you can select or drag your file in this lightning component

JavaScript Controller : fileUploadController.js
/*
 * Source : sfdcmonkey.com 
 * Date : 25/9/2017
 * Locker Service Ready code.
 */
({
    doSave: function(component, event, helper) {
        if (component.find("fileId").get("v.files").length > 0) {
            helper.uploadHelper(component, event);
        } else {
            alert('Please Select a Valid File');
        }
    },

    handleFilesChange: function(component, event, helper) {
        var fileName = 'No File Selected..';
        if (event.getSource().get("v.files").length > 0) {
            fileName = event.getSource().get("v.files")[0]['name'];
        }
        component.set("v.fileName", fileName);
    },
})
JavaScript Helper : fileUploadHelper.js
/*
 * Source : sfdcmonkey.com 
 * Date : 25/9/2017
 * Locker Service Ready code.
 */
({
    MAX_FILE_SIZE: 4500000, //Max file size 4.5 MB 
    CHUNK_SIZE: 750000,      //Chunk Max size 750Kb 
    
    uploadHelper: function(component, event) {
        // start/show the loading spinner   
        component.set("v.showLoadingSpinner", true);
        // get the selected files using aura:id [return array of files]
        var fileInput = component.find("fileId").get("v.files");
        // get the first file using array index[0]  
        var file = fileInput[0];
        var self = this;
        // check the selected file size, if select file size greter then MAX_FILE_SIZE,
        // then show a alert msg to user,hide the loading spinner and return from function  
        if (file.size > self.MAX_FILE_SIZE) {
            component.set("v.showLoadingSpinner", false);
            component.set("v.fileName", 'Alert : File size cannot exceed ' + self.MAX_FILE_SIZE + ' bytes.\n' + ' Selected file size: ' + file.size);
            return;
        }

        // create a FileReader object 
        var objFileReader = new FileReader();
        // set onload function of FileReader object   
        objFileReader.onload = $A.getCallback(function() {
            var fileContents = objFileReader.result;
            var base64 = 'base64,';
            var dataStart = fileContents.indexOf(base64) + base64.length;

            fileContents = fileContents.substring(dataStart);
            // call the uploadProcess method 
            self.uploadProcess(component, file, fileContents);
        });

        objFileReader.readAsDataURL(file);
    },

    uploadProcess: function(component, file, fileContents) {
        // set a default size or startpostiton as 0 
        var startPosition = 0;
        // calculate the end size or endPostion using Math.min() function which is return the min. value   
        var endPosition = Math.min(fileContents.length, startPosition + this.CHUNK_SIZE);

        // start with the initial chunk, and set the attachId(last parameter)is null in begin
        this.uploadInChunk(component, file, fileContents, startPosition, endPosition, '');
    },


    uploadInChunk: function(component, file, fileContents, startPosition, endPosition, attachId) {
        // call the apex method 'saveChunk'
        var getchunk = fileContents.substring(startPosition, endPosition);
        var action = component.get("c.saveChunk");
        action.setParams({
            parentId: component.get("v.parentId"),
            fileName: file.name,
            base64Data: encodeURIComponent(getchunk),
            contentType: file.type,
            fileId: attachId
        });

        // set call back 
        action.setCallback(this, function(response) {
            // store the response / Attachment Id   
            attachId = response.getReturnValue();
            var state = response.getState();
            if (state === "SUCCESS") {
                // update the start position with end postion
                startPosition = endPosition;
                endPosition = Math.min(fileContents.length, startPosition + this.CHUNK_SIZE);
                // check if the start postion is still less then end postion 
                // then call again 'uploadInChunk' method , 
                // else, diaply alert msg and hide the loading spinner
                if (startPosition < endPosition) {
                    this.uploadInChunk(component, file, fileContents, startPosition, endPosition, attachId);
                } else {
                    alert('your File is uploaded successfully');
                    component.set("v.showLoadingSpinner", false);
                }
                // handel the response errors        
            } else if (state === "INCOMPLETE") {
                alert("From server: " + response.getReturnValue());
            } else if (state === "ERROR") {
                var errors = response.getError();
                if (errors) {
                    if (errors[0] && errors[0].message) {
                        console.log("Error message: " + errors[0].message);
                    }
                } else {
                    console.log("Unknown error");
                }
            }
        });
        // enqueue the action
        $A.enqueueAction(action);
    }
})
  • see code comments.
From developer console >> file >> new >> Lightning Application
demo.app [Lightning Application]
<aura:application extends="force:slds">
    <c:fileUpload/>
<!-- here c: is org. default namespace prefix-->
</aura:application>

Output:

upload file using lightning sfdmconkey

Related Resource:

Like our facebook page for new post updates. & Don’t forget to bookmark this site for your future reference.

if you have any suggestions or issue with it, you can share your thoughts  in comment box.

Happy Learning 🙂

55 comments

  • Hi Friends,

    I have one doubt, I am using document object for profile pictures it is not allowing more than 1 Mb file in side the Salesforce. I want to increase capacity from 1 Mb to 4 Mb please tell how can I achieve that.

    Here given below link which I am using for picture upload.

    https://developer.salesforce.com/blogs/developer-relations/2015/11/create-lightning-component-drag-drop-profile-pictures.html

     

    Please help me where I need to do changes for 4 Mb file uploading

     

    Thanks in Advance.

     

    Regards,

    Rajesh

     

  • Hi Team,

    What is the maximum file size that we can upload?

    I have tried and observed that we can upload only maximum of 4.5MB file, As there is an exception being thrown from apex i.e. Heap Exception on string value is crossing 6MB.

    Is there any other alternative way that we can upload file of more than 5MB?

     

     

  • Absolutly right. From Apex you can upload only 4.5 Mb attachments. It depends on heap size limit for String class (6Mb). Because we using base64 encoding we will take only 6*0.75=4.5Mb. But If you can upload file from 3-party server this size will grow. I want tell about Rest API. For Attachment limit is 25Mb. If you choise Document you can upload up to 2Gb. If you choise other Object with Blob field it is only 500Mb.

  • Hi Guys,

    The above code is not working for me. I mean it is not throwing any exception at the same time all the time the spinner is rendering and attachment also not get created in Salesforce.

    Please let me know. Thanks!

  • Hi Team,

    The above code is not working for me. When I have upload a image all the time spinner is rendering and image also not inserting in side the salesforce. Please let me know. Thanks!

  • It is not working. From last 1 hour spinner is rotating. the attachment is not saved in any object

    • Update the ParentId from the code above to the object ID to which you want to save the attachment and it should work. Thanks.

      • Thank you, now we can save the code into object but we should hard code the id of account object.can you please guide me.

  • Hi Everyone,

    Can you help me to use this component to upload attachment before saving the record.
    The scenario is the user has to upload the document while creating the record.

  • I updated all classes from parentId to caseId. But i get an error on line 27 “Variable does not exist: caseId”

  • How can I pass a flow variable into the controller where you have hard coded the account id? Please help me, I am stuck at this point.

  • Hi Piyush,

     

    Could you please help me, I want to replace parentId with the dynamic caseid from my flow. How can I accomplish this to pass flow output variable to this lightning component.

     

    Regards

    Chetan Bhatla

     

    • I got it working, getting a flow variable into this lighning component. Thanks for this amazing article. this solved my problem of attaching a file with the case by community guest user who does not have Edit access on case object.

      Thanks Again.

  • Hello,

    You can include a attribute called as accept in the lightning:input tag. By this way you can restrict the types of attachments that can be uploaded. Also you can specify if you need to access the camera on a smatrphone or a tablet using the salesforce1 app or also if salesforce is opened from a mobile browser. This is a very good use case for service engineers to capture images on the go and upload it to any record.

     

    • Hi Nitesh,
      i want to accomplish kind of same you mentioned, i am creating a Component to create Account Record in which i want to get the image as well, for that i have tried (Lightning:upload) but it does not have (onClick) attribute so i decided to build custom upload with this article but i am unable to save the component it throws an error
      “Failed to save fileUploader.cmp: Invalid definition for FileUploaderController: ApexService.getType() return null with currentNamespace: c, namespace: null, name: FileUploaderController: Source ”
      can you help me with that?

  • I want to upload more than 1GB file, based on Chunks, is there any solution or proper way to devlope the code throght lightning component apex.

  •  private static void appendToFile(Id fileId, String base64Data) {
            base64Data = EncodingUtil.urlDecode(base64Data, ‘UTF-8’);

            Attachment a = [
                SELECT Id, Body
                FROM Attachment
                WHERE Id =: fileId
            ];

            String existingBody = EncodingUtil.base64Encode(a.Body);

            a.Body = EncodingUtil.base64Decode(existingBody + base64Data);

            update a;
        }
     hi piyush i need test class for this method could you please provide if possible…thanks

  • Hi ,

    I am using the above code to save attachment.After inserting it is returning attachment but when i query the record with the returned Id it is giving me zero results.FileId is not null.
    Attachment a = [
    SELECT Id, Body
    FROM Attachment
    WHERE Id =: fileId
    ];

    Can you please let me know if it is still pending or why is it returning zero results?

    Thanks

  • Hi ,
    I am using the above code. After inserting attachment it is returning Id, but when I fetch the record by SOQL query it is returning me no records.
    Attachment a = [
    SELECT Id, Body
    FROM Attachment
    WHERE Id =: fileId
    ];

    Can you please let me know why is it returning zero records?Is it still pending for insertion

  • Hi Piush,

    This code worked for me, but only upto 4.5MB files are uploading. Is there any way to upload bigger files like (10-25MB) files.

     

    Thanks

  • Hi Piush,

    This code worked for me, but only upto 4.5 files are uploading is there any way to upload bigger files like (10-20MB) files.

     

    Thanks

  • Hi ,

    I want to Parse the Excel file using lightning component.Please do the needful.

    Regards,

    Ashish

  • Hi Piyush,

    I want to have the same kind of functionality but i want to save the browsed image to document object.how can i do that?

  • Hi Piyush,

    your checking the file size in helper.it is not working properly
     if (file.size > self.MAX_FILE_SIZE) {
                component.set(“v.showLoadingSpinner”, false);
                component.set(“v.fileName”, ‘Alert : File size cannot exceed ‘ + self.MAX_FILE_SIZE + ‘ bytes.\n’ + ‘ Selected file size: ‘ + file.size);
                return;
            }
    here i want restrict the file size is 3mb.its not working properly.
     

  • Can this code work for standalone lightning component?

    I have registeration form,i need to attach resume upload functionality to it. But your code doesnt work , as it keep spinnng and file never saves.

  • Hi. Piyush,,

    Im using the above code and created custom case componets but im unable to attch files morethen 2 Mb Pdf or ther files. Spinner shoulf be loading after 2MB files loaded. It works fime for small files below 1. 5 Mb. How can it work for others to uplaod upto 4.5 Mb. Any one tell me plz…. And ho can we increase upto 10 mb

     

     

    Thank you

    Emran

  • HI, Piyush

    by using this code im unable to upload file more then 1.5 mb, but you said limit is 4.5 mb, if i upload filesize morethen 2mb spinner should loading and file not attached, the debug log says apex heap size limit is more then the limit. how can we resolve this issue. pls update me

     

     

     

    Thank you

     

    emran

     

  • I am creating a Component to create Account Record in which i want to get the image as well, for that i have tried (Lightning:upload) but it does not have (onClick) attribute so i decided to build custom upload with this article but i am unable to save the component it throws an error
    “Failed to save fileUploader.cmp: Invalid definition for FileUploaderController: ApexService.getType() return null with currentNamespace: c, namespace: null, name: FileUploaderController: Source ”
    can you help me with that?

  • code is not working for me.

    After clicking on Upload Attachment button, it keeps spinning.

    I have changed parentId as well. Plz help me any workaround?

  • Hii, can you please explain how to get parentId and attachId dynamically. I badly want to this.

  • Hello,  this code worked for me but i cannot see where is file uploaded its neither in files nor in documents tab.Please tell me where to find it.

Leave a Reply