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>
Output: