File Upload Component:
Create a new Lightning Component FileUpload.cmp
.
<!--FileUpload.cmp--> <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="00128000002KuXUAA0" /> <!-- '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="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="Cancel" onclick="{!c.handleCancel}" class="slds-m-top--medium" /> <lightning:button label="Save" onclick="{!c.handleSave}" variant="brand" class="slds-m-top--medium"/> </aura:component>
File Upload JavaScript Controller:
Now create below JavaScript FileUploadController.js
controller for above FileUpload.cmp
component.
({ handleSave: function(component, event, helper) { if (component.find("fuploader").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); }, handleCancel: function(component, event, helper) { $A.get("e.force:closeQuickAction").fire(); } })
File Upload JavaScript Controller Helper:
Now create below JavaScript FileUploadHelper.js
helper for above FileUploadController.js
component.
({ MAX_FILE_SIZE: 4500000, //Max file size 4.5 MB CHUNK_SIZE: 750000, //Chunk Max size 750Kb uploadHelper: function(component, event) { // get the selected files using aura:id [return array of files] var fileInput = component.find("fuploader").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.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 'SaveFile' var getchunk = fileContents.substring(startPosition, endPosition); var action = component.get("c.SaveFile"); 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('File has been uploaded successfully'); } // 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); } })
File Upload Apex Controller:
Create below apex controller to use it in FileUpload.cmp
component.
public with sharing class FileUploadController { @AuraEnabled public static Id SaveFile(Id parentId, String fileName, String base64Data, String contentType) { base64Data = EncodingUtil.urlDecode(base64Data, 'UTF-8'); Attachment attach = new Attachment(); attach.parentId = parentId; attach.Body = EncodingUtil.base64Decode(base64Data); attach.Name = fileName; attach.ContentType = contentType; Insert attach; return attach.Id; } }
File Upload App:
<!--FileUploadApp.app--> <aura:application extends="force:slds"> <c:FileUpload /> </aura:application>