I have developed a lightning component to upload files into the File Salesforce object.
This component has been developed based on Peter Knolle article on how to do that in the lightning framework.
This component has been working good for over a year - until 2 weeks ago (maybe Winter 18 is the cause of the change).
The problem is that I create an action to send to the server, set it's params, set it's callback, and then use the $A.enqueueAction(action);
command.
Now - the action is queued but not executing.
I have used the chrome lightning inspector extension and the action is clearly pending:
And it is stuck forever, unless I close the component or something like that.
This is my component:
FileUpload.cmp
<aura:component controller="Attachment_CTRL">
<aura:attribute name="parentId" type="Id"/>
<aura:attribute name="fileMetadata" type="Object" description="the metadata of the file that was uploaded to the client - before saving to server" access="private" />
<aura:attribute name="fileData" type="Object" description="the actual file that was uploaded to the client - before saving to server" access="private"/>
<aura:method name="executeUpload" action="{!c.executeUpload}" description="Fire the executeUpload controller method">
<aura:attribute name="fileMetadata" type="Object" />
<aura:attribute name="fileData" type="Object"/>
</aura:method>
<div class="slds-form-element" title="max 750 Kb">
<div class="slds-form-element__control">
<div class="slds-file-selector slds-file-selector--files">
<input class="slds-file-selector__input slds-assistive-text" type="file" onchange="{!c.save}" aura:id="file" id="file-upload-input-01" aria-describedby="file-selector-id" />
<label class="slds-file-selector__body" for="file-upload-input-01">
<span class="slds-file-selector__button slds-button slds-button--neutral">
<lightning:icon iconName="utility:add" size="x-small" /> Add File
</span>
</label>
</div>
</div>
</div>
<lightning:spinner aura:id="uploadingSpinner" size="large" class="slds-hide" />
</aura:component>
FileUploadController.js
({
// MAX_FILE_SIZE: 750000, /* 1 000 000 * 3/4 to account for base64 */
save: function(component, event, helper) {
var fileInput = component.find("file");
var fileElement = fileInput.getElement();
var fileMetadata = fileElement.files[0];
if (fileMetadata.size > 750000) {
alert("File size is too big!!!");
return;
}
var fr = new FileReader();
fr.onload = function() {
var fileData = fr.result;
var base64Mark = 'base64,';
var dataStart = fileData.indexOf(base64Mark) + base64Mark.length;
fileData = fileData.substring(dataStart);
// TODO: this aura:method is used because straight server side call does not execute from within FileReader
// call server through aura:method to override server action not executing problem
component.executeUpload(fileMetadata, fileData);
};
// run file reader for downloading file
fr.readAsDataURL(fileMetadata);
},
executeUpload: function(component, event, helper) {
var params = event.getParam('arguments');
if (params) {
var fileMetadata = params.fileMetadata;
var fileData = params.fileData;
var parentId = component.get("v.parentId");
helper.uploadFile(component, fileMetadata, fileData, parentId);
}
}
})
FileUploadHelper.js
({
uploadFile: function(component, fileMetadata, fileData, parentId) {
// get server side method
var action = component.get("c.upload");
// set all file params
action.setParams({
parentId: parentId,
fileName: fileMetadata.name,
base64Data: encodeURIComponent(fileData),
contentType: fileMetadata.type
});
// set the callback function
action.setCallback(this, function(response) {
var state = response.getState();
if (component.isValid() && state === "SUCCESS") {
alert("File uploaded successfully");
}
else { // tell parent file was not added:
alert("Error uploading file");
}
// turn spinner off - after finished uploading
this.toggleSpinner(component);
});
// execute server side action
$A.enqueueAction(action);
},
toggleSpinner: function(component) {
var spinner = component.find("uploadingSpinner");
$A.util.toggleClass(spinner, "slds-hide");
}
})
Attachment_CTRL.cls
public without sharing class Attachment_CTRL {
@AuraEnabled
public static Id upload(Id parentId, String fileName, String base64Data, String contentType) {
system.debug('Attachment_CTRL.upload start for Id: ' + parentId + ', file name: ' + fileName);
String decodedData = EncodingUtil.urlDecode(base64Data, 'UTF-8');
Blob body = EncodingUtil.base64Decode(decodedData);
Attachment newAttachment = new Attachment();
newAttachment.parentId = parentId;
newAttachment.Name = fileName;
newAttachment.Body = body;
newAttachment.ContentType = contentType;
insert newAttachment;
return newAttachment.Id;
}
}
My question is: am I doing something wrong? why is the action not executing? how can I fix this and execute the action?