<c:FileUpload parentId="" label="" />
Last active
March 14, 2024 10:24
-
-
Save SalesforceBobLightning/7e244fe097390000c45a7db2a0957aa4 to your computer and use it in GitHub Desktop.
Salesforce Lightning FileUpload Component
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
<aura:component controller="FileUploadController"> | |
<aura:attribute name="parentId" type="Id" /> | |
<aura:attribute name="label" type="String" /> | |
<aura:attribute name="uploading" type="Boolean" default="false" /> | |
<aura:handler event="aura:waiting" action="{!c.waiting}" /> | |
<aura:handler event="aura:doneWaiting" action="{!c.doneWaiting}" /> | |
<aura:if isTrue="{!v.uploading}"> | |
<lightning:spinner alternativeText="Loading" size="large" /> | |
</aura:if> | |
<div> | |
<div class="slds-form-element"> | |
<span class="slds-form-element__label" id="file-selector-primary-label">{! v.label }</span> | |
<div class="slds-form-element__control"> | |
<div class="slds-file-selector slds-file-selector_files"> | |
<div class="slds-file-selector__dropzone"> | |
<input aura:id="file" class="slds-file-selector__input slds-assistive-text" type="file" id="file-upload-input-01" | |
aria-labelledby="file-selector-primary-label file-selector-secondary-label" /> | |
<label class="slds-file-selector__body" for="file-upload-input-01" id="file-selector-secondary-label"> | |
<span class="slds-file-selector__button slds-button slds-button_neutral"> | |
<lightning:icon iconName="utility:upload" size="xx-small" alternativeText="upload" />Upload | |
Files</span> | |
<span class="slds-file-selector__text slds-medium-show">or Drop Files</span> | |
<span> | |
<ui:button label="Upload" press="{!c.save}" /> | |
</span> | |
</label> | |
</div> | |
</div> | |
</div> | |
</div> | |
</div> | |
</aura:component> |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
.THIS .notUploading { | |
visibility: hidden; | |
} | |
.THIS .uploading { | |
visibility: visible; | |
display: inline-block; | |
margin-top: 10px; | |
} | |
.THIS .small-spinner { | |
height: 20px; | |
width: 20px; | |
} | |
.THIS .file { | |
margin-bottom: 5px; | |
display: block; | |
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
public without sharing class FileUploadController { | |
@AuraEnabled | |
public static Id saveTheFile(Id parentId, String fileName, String base64Data, String contentType) { | |
base64Data = EncodingUtil.urlDecode(base64Data, 'UTF-8'); | |
ContentVersion contentVersion = new ContentVersion( | |
versionData = EncodingUtil.base64Decode(base64Data), | |
title = fileName, | |
pathOnClient = '/' + fileName, | |
FirstPublishLocationId = parentId); | |
insert contentVersion; | |
return contentVersion.Id; | |
} | |
@AuraEnabled | |
public static Id saveTheChunk(Id parentId, String fileName, String base64Data, String contentType, String fileId) { | |
if (fileId == '') { | |
fileId = saveTheFile(parentId, fileName, base64Data, contentType); | |
} else { | |
appendToFile(fileId, base64Data); | |
} | |
return Id.valueOf(fileId); | |
} | |
private static void appendToFile(Id fileId, String base64Data) { | |
base64Data = EncodingUtil.urlDecode(base64Data, 'UTF-8'); | |
ContentVersion contentVersion = [ | |
SELECT Id, versionData | |
FROM ContentVersion | |
WHERE Id = :fileId | |
]; | |
String existingBody = EncodingUtil.base64Encode(contentVersion.versionData); | |
contentVersion.versionData = EncodingUtil.base64Decode(existingBody + base64Data); | |
update contentVersion; | |
} | |
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
({ | |
save: function (component, event, helper) { | |
helper.save(component); | |
}, | |
waiting: function (component, event, helper) { | |
component.set("v.uploading", true); | |
}, | |
doneWaiting: function (component, event, helper) { | |
component.set("v.uploading", false); | |
} | |
}) |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
({ | |
MAX_FILE_SIZE: 4500000, /* 6 000 000 * 3/4 to account for base64 */ | |
CHUNK_SIZE: 950000, /* Use a multiple of 4 */ | |
save: function (component) { | |
var fileInput = component.find("file").getElement(); | |
var file = fileInput.files[0]; | |
if (file.size > this.MAX_FILE_SIZE) { | |
alert('File size cannot exceed ' + this.MAX_FILE_SIZE + ' bytes.\n' + | |
'Selected file size: ' + file.size); | |
return; | |
} | |
var fr = new FileReader(); | |
var self = this; | |
fr.onload = function () { | |
var fileContents = fr.result; | |
var base64Mark = 'base64,'; | |
var dataStart = fileContents.indexOf(base64Mark) + base64Mark.length; | |
fileContents = fileContents.substring(dataStart); | |
self.upload(component, file, fileContents); | |
}; | |
fr.readAsDataURL(file); | |
}, | |
upload: function (component, file, fileContents) { | |
var fromPos = 0; | |
var toPos = Math.min(fileContents.length, fromPos + this.CHUNK_SIZE); | |
// start with the initial chunk | |
this.uploadChunk(component, file, fileContents, fromPos, toPos, ''); | |
}, | |
uploadChunk: function (component, file, fileContents, fromPos, toPos, attachId) { | |
console.log('uploadChunk'); | |
var action = component.get("c.saveTheChunk"); | |
var chunk = fileContents.substring(fromPos, toPos); | |
action.setParams({ | |
parentId: component.get("v.parentId"), | |
fileName: file.name, | |
base64Data: encodeURIComponent(chunk), | |
contentType: file.type, | |
fileId: attachId | |
}); | |
var self = this; | |
action.setCallback(this, function (a) { | |
console.log('uploadChunk: Callback'); | |
attachId = a.getReturnValue(); | |
fromPos = toPos; | |
toPos = Math.min(fileContents.length, fromPos + self.CHUNK_SIZE); | |
if (fromPos < toPos) { | |
self.uploadChunk(component, file, fileContents, fromPos, toPos, attachId); | |
} else { | |
console.log('uploadChunk: done'); | |
self.showToast('Upload Complete', 'You file has successfully uploaded, please upload another now.', 'success', null); | |
} | |
}); | |
$A.getCallback(function () { | |
$A.enqueueAction(action); | |
})(); | |
}, | |
showToast: function (title, message, type, icon) { | |
var toastEvent = $A.get("e.force:showToast"); | |
toastEvent.setParams({ | |
title: title, | |
message: message, | |
duration: '2000', | |
key: icon, | |
type: type, | |
mode: 'dismissible' | |
}); | |
toastEvent.fire(); | |
}, | |
}) |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment