Files Upload and Preview using Lightning Aura
In Salesforce, files refer to any type of document or digital asset that can be stored, shared, and
collaborated on within the platform. By leveraging Salesforce’s file management system capabilities,
organizations can improve collaboration and enhance productivity and ensure security of their data.
In this post we are going to implement requirement of uploading multiple files using lightning aura component as well as preview uploaded document. Below are some objects which are associated with storing the document.
Objects
-
ContentDocument
: It represents a document that has been uploaded on salesforce platform. Some important fields areFileExtension
determines extension of file andFileType
determine byFileExtension
,Title
stores tile of document,ContentSize
size of documents in bytes. ContentDocumentLink
: Record ofContentDocumentLink
represent link betweenContentDocument
and another object in salesforce. For example if file is related to Account record then there will becontentDocumentLink
record connectingContentDocument
toAccount
. Some important fields areContentDocumentId
is related toContentDocument
object through lookup relationship contains Id of document.LinkedEntityId
is a lookup relationship contains Id of related or linked object.ShareType
is the permission granted to the user of the shared file in a library. V: (Viewer) User can explicitly view but cannot edit file. C: (Collaborator) User can view and edit shared files. I: (Inferred) determine by the related record.ContentVersion
: This object represents specific version of file that has been edited or uploaded on salesforce. MultipleContentVersion
records can be linked with samecontentDocument
record.
Source Code
Apex
public class FileUploadController { @AuraEnabled public static String fileUpload (String parentId, String name, String fileType, String fileData){ try{ System.debug('**fileData** '+EncodingUtil.base64Decode(fileData)); ContentVersion fileVersion = new ContentVersion(); fileVersion.Title = name; fileVersion.PathOnClient = name; fileVersion.VersionData = EncodingUtil.base64Decode(fileData); insert fileVersion; System.debug('**fileVersion** '+fileVersion); ContentDocumentLink newLink = new ContentDocumentLink(); newLink.LinkedEntityId = parentId; newLink.ShareType = 'V'; newLink.ContentDocumentId = [SELECT Id,ContentDocumentId FROM ContentVersion WHERE Id=:fileVersion.Id].ContentDocumentId; insert newLink; return String.valueOf(newLink.ContentDocumentId); } catch(Exception ex){ System.debug('Exception occured on line No. '+ex.getLineNumber() +'Error Message '+ex.getMessage()); throw new AuraHandledException('Exception: ' + ex.getMessage() + 'on Line Number: '+ex.getLineNumber()); } } }
Lightning Component
<aura:component implements="force:appHostable,flexipage:availableForAllPageTypes,flexipage:availableForRecordHome,force:hasRecordId,forceCommunity:availableForAllPageTypes,force:lightningQuickAction" access="global" controller="FileUploadController"> <aura:attribute name="recordId" type="string"/> <aura:attribute name="contentDocIds" type="List" access="global"/> <aura:attribute name="fileName" type="List" access="global"/> <lightning:spinner aura:id="mySpinner" title="Uploading..." varient="brand" class="slds-hide"/> <div class="slds-grid slds-gutters"> <div class="slds-col"> <lightning:input type="file" aura:id="fileUpload" label="File Upload" name="file" multiple="true" onchange="{!c.filesChangeHandler}"/> <aura:if isTrue="{!v.fileName.length > 0}"> <aura:iteration items="{!v.fileName}" var="val"> <div class="slds-text-color_success"> {!val}<br/> </div> </aura:iteration> <aura:set attribute="else"> <div class="slds-text-color_error"> No Files Selected... </div> </aura:set> </aura:if> <lightning:button name="Upload File" label="Upload File" variant="brand" onclick="{!c.uploadFiles}"/> </div> </div> <br/> <div class="slds-grid slds-gutters"> <aura:if isTrue="{!v.contentDocIds.length > 0}"> <aura:iteration items="{!v.contentDocIds}" var="val"> <div class="slds-col"> <lightning:fileCard fileId="{!val}"/> </div> </aura:iteration> </aura:if> </div> </aura:component>
Controller
({ filesChangeHandler: function(component, event, helper){ var files = component.find("fileUpload").get("v.files"); var fileName = []; Array.from(files).forEach((file,index) => { fileName.push(file.name); }); component.set("v.fileName",fileName); }, uploadFiles: function(component, event, helper){ $A.util.removeClass(component.find("mySpinner"),"slds-hide"); var files = component.find("fileUpload").get("v.files"); if(!$A.util.isEmpty(files) && !$A.util.isUndefinedOrNull(files)){ if(files.length > 0){ helper.uploadFiles(component, event, helper, files); } else{ $A.util.addClass(component.find("mySpinner"),"slds-hide"); helper.showToast(component, 'error', 'Please Select File to Upload') } } else{ $A.util.addClass(component.find("mySpinner"),"slds-hide"); helper.showToast(component, 'error', 'Please Select File to Upload'); } }, })
Helper
({ uploadFiles: function(component, event, helper, files){ var self = this; Array.from(files).forEach((file,index) => { var readFile = new FileReader(); readFile.onload = $A.getCallback(function() { var fileData = readFile.result; fileData = fileData.substring(fileData.indexOf('base64,') + 'base64,'.length) self.insertDocuments(component, event, helper, fileData, file); }); readFile.readAsDataURL(file); }); }, insertDocuments: function(component, event, helper, fileData, file){ $A.util.removeClass(component.find("mySpinner"),"slds-hide"); var parentId = component.get("v.recordId"); var size = file.size; var fileName = file.name; var fileType = file.type; var action = component.get("c.fileUpload"); action.setParams({ 'parentId': parentId, 'name': fileName, 'fileType': fileType, 'fileData': fileData }); action.setCallback(this, function(response){ var state = response.getState(); $A.util.addClass(component.find("mySpinner"),"slds-hide"); if(state === 'SUCCESS'){ var result = response.getReturnValue(); if(!$A.util.isEmpty(result) && !$A.util.isUndefinedOrNull(result)){ var contentDocIds = component.get("v.contentDocIds"); contentDocIds.push(result); component.set("v.contentDocIds",contentDocIds); var emptyFiles = []; component.find("fileUpload").set("v.files",null); component.set("v.fileName",emptyFiles); this.showToast(component, 'success','Document Inserted Successfully'); } else{ this.showToast(component, 'error','Something went wrong, Not able to fetch ContentDocumentId'); } } else{ var errors = response.getError(); if(errors){ this.showToast(component, 'error','Exception occured'); } } }); $A.enqueueAction(action); }, showToast: function(cmp, type, message){ var notification = $A.get("e.force:showToast"); notification.setParams({ message: message, duration: '1000', type: type, mode: 'pester' }); notification.fire(); } })