Upload a file to Salesforce File from Lightning Component

In my recent work for a client, there was a need to upload a file to a case not as an attachment but upload under Files Section. As you are aware, Salesforce Files are replacing Attachment. In this post, I am sharing the code end to end for your reference.

In this case, I created a new case and attached file under it, you can also pass a recordId/parentId if you already have the record to which files needs to be attached

FileUpload Component

<aura:component description="FileUpload" implements="flexipage:availableForAllPageTypes,flexipage:availableForRecordHome,force:hasRecordId" controller="FileUploadController">
 
    <aura:attribute name="recordId" type="String" description="Record to which the files should be attached" />
    <aura:attribute name="fileName" type="String" default="No File Selected.." />
    
    
        <lightning:layoutItem class="slds-p-around--xx-small" size="12" smallDeviceSize="12" mediumDeviceSize="12" largeDeviceSize="12">

        <div class="slds-grid slds-wrap">
            <div class="slds-size_2-of-2">

              <lightning:card>
                    <aura:set attribute="actions">
            			<button class="slds-button slds-button_neutral">Upload Offline File</button>
                    </aura:set>
                  
                    <div class="slds-p-bottom_medium slds-p-left_medium slds-border_bottom">
                        <div class="slds-media">
                            <div class="slds-media__figure slds-p-right_medium">
                            <div class="slds-icon slds-page-header__icon ">
                                <lightning:icon iconName="action:user" size="small"/>
                            </div>
                            </div>
                            <div class="slds-media__body">
                                <div class="slds-p-top_small">
                                <h1>
                                    <span class="slds-page-header__title" title="Upload File">Upload File</span>
                                </h1>
                                </div>
                            </div>
                        </div>
                        </div>


                        <div class="slds-p-around_medium">

                            <div style="overflow: auto;" >
                                <div style="min-width: 600px;">
                                    <div class="slds-p-around--small">
                                       
                                        <!-- Lightning Input with file type and on file change call the 'handleFilesChange' controller -->
                                        <lightning:input aura:id="fuploader" onchange="{!c.handleFilesChange}" type="file" name="file" label="Upload File" multiple="false"/>
                                        <div class="slds-text-body_small slds-text-color_error">{!v.fileName} </div>
                                        <br/>
                                        <lightning:button label="Save" onclick="{!c.handleSave}"
                                                        variant="brand" class="slds-m-top--medium"/>

                                        
                                    </div>
                                </div>
                            </div>
                       
                        </div>

                </lightning:card>
 
            </div>
        </div>
    
        </lightning:layoutItem>
    </div>

    
    
 </aura:component>

Controller Js File

({
	handleUploadFinished : function(component, event, helper) {
        var uploadedFiles = event.getParam("files");
        var documentId = uploadedFiles[0].documentId;
        var fileName = uploadedFiles[0].name;
        helper.showToast('Success','Success','File Uploaded successfully');        
    },
    
    handleSave: function(component, event, helper) {

        if (component.find("fuploader").get("v.files")!=null && component.find("fuploader").get("v.files").length > 0) {
            helper.uploadHelper(component, event);
        } else {
            helper.showToast('Error','Error','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);
    },


})

Helper Js File

({
    
    MAX_FILE_SIZE: 4500000, //Max file size 4.5 MB 
    CHUNK_SIZE: 750000,      //Chunk Max size 750Kb 
     
    uploadHelper: function(component, event) {
        var fileInput = component.find("fuploader").get("v.files");
        var file = fileInput[0];
        var self = this;
        if (file.size > self.MAX_FILE_SIZE) {
            component.set("v.fileName", 'Alert : File size cannot exceed ' + self.MAX_FILE_SIZE + ' bytes.\n' + ' Selected file size: ' + file.size);
            return;
        }
         
        var objFileReader = new FileReader();
        objFileReader.onload = $A.getCallback(function() {
            var fileContents = objFileReader.result;
            var base64 = 'base64,';
            var dataStart = fileContents.indexOf(base64) + base64.length;
             
            fileContents = fileContents.substring(dataStart);
            self.uploadProcess(component, file, fileContents);
        });
         
        objFileReader.readAsDataURL(file);
    },
     
    uploadProcess: function(component, file, fileContents) {
        var startPosition = 0;
        var endPosition = Math.min(fileContents.length, startPosition + this.CHUNK_SIZE);
        this.uploadInChunk(component, file, fileContents, startPosition, endPosition, '');
    },
     
     
    uploadInChunk: function(component, file, fileContents, startPosition, endPosition, attachId) {
        var getchunk = fileContents.substring(startPosition, endPosition);
        var action = component.get("c.uploadFile");
        action.setParams({
            fileName: file.name,
            base64Data: encodeURIComponent(getchunk),
            contentType: file.type,
            fileId: attachId
        });
         
        // set call back 
        action.setCallback(this, function(response) {
            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);
                if (startPosition < endPosition) {
                    this.uploadInChunk(component, file, fileContents, startPosition, endPosition, attachId);
                } else {
                    this.showToast('Success','Success','File Uploaded successfully');   
                }
            } else if (state === "INCOMPLETE") {
                this.showToast('Error','Error','Issue in uploading File '+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);
                        this.showToast('Error','Error','Issue in uploading File '+errors[0].message);   
                    }
                } else {
                    console.log("Unknown error");
                }
            }
        });
        // enqueue the action
        $A.enqueueAction(action);
    },

    showToast : function(type, title, message) {
        var toastEvent = $A.get("e.force:showToast");
        toastEvent.setParams({
            "type": type,
            "title": title,
            "message": message
        });
        toastEvent.fire();
    },
         
    
})

FileUploadController.cls

public with sharing class FileUploadController {

    private static final String ISSUE_UPLOADING_FILE = 'There is a problem in uploading the file';
    
    @AuraEnabled
    public static Id uploadFile(String fileName, String base64Data, String contentType) {
        
        Contact instructorContact = UserContactRetriever.getContact();
        Case caseObj = new Case(Status='Working',Origin='Community',Subject='Offline Attendance Upload',Contact=instructorContact);
        try{  
            insert caseObj;        
            base64Data = EncodingUtil.urlDecode(base64Data, 'UTF-8');              
            ContentVersion cv = createContentVersion(base64Data, filename);
            ContentDocumentLink cdl = createContentDocumentLink(cv.Id, caseObj.Id);
            if (cv == null || cdl == null) { return null; }
            return cdl.Id;   
            }         
         catch(Exception exc) {
            System.debug('Error: ' + exc.getStackTraceString() + ' ' + exc.getMessage());
            Logger.logMessage(exc.getMessage(),'User: '+UserInfo.getName(),'INST_FileUploadController','SaveFile()',String.valueOf(exc.getLineNumber()),exc.getTypeName(), exc.getStackTraceString() ,null);  
            throw new AuraHandledException(ISSUE_UPLOADING_FILE);
        }   
    }
    
    private static ContentVersion createContentVersion(String base64, String filename) {
        ContentVersion cv = new ContentVersion();
        cv.VersionData = EncodingUtil.base64Decode(base64);
        cv.Title = filename;
        cv.ContentLocation = 'S';
        cv.PathOnClient = filename;
          insert cv;
          return cv;
      }
  
      private static ContentDocumentLink createContentDocumentLink(String contentVersionId, String recordId) {
           if (contentVersionId == null || recordId == null) { return null; }
              
            ContentDocumentLink cdl = new ContentDocumentLink();
            cdl.ContentDocumentId = [
              SELECT ContentDocumentId 
              FROM ContentVersion 
              WHERE Id =: contentVersionId
            ].ContentDocumentId;
    
            cdl.LinkedEntityId = recordId;
            cdl.ShareType = 'V';
            cdl.Visibility = 'InternalUsers';
              insert cdl;
              return cdl;
          }    
    
}

Permanent link to this article: https://salesforcebuddy.com/2020/06/upload-a-file-to-salesforce-file-from-lightning-component/

Leave a Reply

Your email address will not be published.