function readOnly(count){ }
Starting November 20, the site will be set to read-only. On December 4, 2023,
forum discussions will move to the Trailblazer Community.
+ Start a Discussion
sukanta Anbu 7sukanta Anbu 7 

Getting 'Cannot read property 'getElement' of undefined' in my jscript

I have a lightning component for drag and drop functionality which should invoke a post callout in apex class and the file should get saved in a external DB . However when i try to upload a file, I am getting the fllowing error.

Action failed: c:Classfileupload$controller$handleFilesChange [Cannot read property 'getElement' of undefined]
Failing descriptor: {c:Classfileupload$controller$handleFilesChange}


The following is my component

<aura:component controller="Classfileupload" implements="force:appHostable,lightning:availableForFlowScreens,force:hasRecordId,force:lightningQuickAction" access="global">
 <!-- 'parentId' Aura Attribute for store the Id for Parent Record where we are attach our file -->  
   <aura:attribute name="recordId" type="String"/>
 <!-- 'showLoadingSpinner' attribute for show/hide the uploading image and msg in aura:if-->
   <aura:attribute name="showLoadingSpinner" type="boolean" default="false" />
 <!-- '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 -->
    <aura:attribute name="jobID" type="String"/>
    <!-- fetches the jobID from the record -->
 
   <lightning:input aura:id="fileId" onchange="{!c.handleFilesChange}" type="file" name="file" label="Upload Attachment" multiple="false"/>
   <div class="slds-text-body_small slds-text-color_error">{!v.fileName} </div>
 
 <!--use aura:if for show-hide the loading spinner image--> 
   <aura:if isTrue="{!v.showLoadingSpinner}">
      <div class="slds-text-body_small slds-text-color_error">Uploading... 
         <img src="/auraFW/resources/aura/images/spinner.gif" class="spinner-img" alt="Loading"/>'
      </div>
   </aura:if>
   
 <br/>
    <lightning:button aura:id="submit" type="button" class="submit" onclick="{!c.doSave}">Upload Attachment</lightning:button>
</aura:component>


The following is my .js file
({
    doSave: function(component, event, helper) {
        var fileInput  = component.find("file").getElement();
        var file = fileInput.files[0];
        console.log('file is coming==>'+file);

        var reader = new FileReader();
   
        reader.onload = function (e) {
            var fileContent = reader.result;
            var base64 = 'base64,';
            var dataStart = fileContent.indexOf(base64) + base64.length;
            fileContent = fileContent.substring(dataStart)
            console.log(fileContent);
            
            var jobID = component.get("v.jobID");
            var recordId = component.get("v.recordId");
            
            var action = component.get("c.POST");
            action.setParams({ file : fileContent, jobID : jobID });
             action.setCallback(this, function(response) {
                var returnValue = response.getReturnValue();
                console.log('returnValue===>'+returnValue);
            
                component.set("v.message", returnValue);
            });
            $A.enqueueAction(action);
        };
        reader.readAsDataURL(file);
        
        var toastEvent = $A.get("e.force:showToast");
        toastEvent.setParams({
            mode: 'sticky',
            message: 'Success',
            messageTemplate: '{0} record created! See it {1}!',
            messageTemplateData: ['Job', {
                url: 'https://csv-file-upload.herokuapp.com/leads/' + jobID,
                label: 'here',
                }
            ]
        });
        toastEvent.fire();
    },
 
    handleFilesChange: function(component, event, helper) {
        
        var input = component.find("file").getElement();
        input.handleFilesChange();
        
        var action = component.get("c.createJob");
        action.setCallback(this, function(response) {
                var returnValue = response.getReturnValue();
                console.log(returnValue);
                
                component.set("v.recordId", returnValue[0]);
                component.set("v.jobID", returnValue[1]);
            });
            $A.enqueueAction(action);
        
        window.setTimeout(
            $A.getCallback(function() {
                $A.util.removeClass(component.find('previewContainer'),"slds-hide");
            }), 5000
        )
    },

})


The following is my apex class

public with sharing class Classfileupload {
 
 @AuraEnabled
    public static List<String> createJob() {
        
        List<String> myList = new List<String>();
          DMS__c dms = new DMS__c(Name='Amtex Demo3',Description__c='Test',Folder__c='Active',Key_Words__c='Test');
        insert dms;
         Id recordId = dms.Id;
      
        DMS__c recdms = [SELECT id, JobID__c, id_reference__c FROM DMS__c WHERE id = :recordId];
       
        update recdms;
        
        myList.add(recordId);
        myList.add(recdms.JobID__c);
        system.debug('ID LIST: ' + myList);
        return myList;
    }
    
    @AuraEnabled
    public static String POST(Blob file, String jobID, String fileName) {
        
        Http h = new Http();
        String url = 'https://csv-file-upload.herokuapp.com/leads/' + jobID;
        String separationString = 'da5cbc76-39ba-4f80-8b81-090b82e90cf0';
        String str = file.toString();
   //     String csvBody = EncodingUtil.base64Encode(csvBlob);
        // decode 
        Blob decodedBlob = EncodingUtil.base64Decode(str);
        system.debug('string ==>'+decodedBlob);
        // convert to string
        String result = decodedBlob.toString();
        
        // assemble the body payload
        String header = '--' + separationString + '\nContent-Disposition: form-data; name="file"; filename="' + fileName + '"\nContent-Type: application/octet-stream\n\n';
        //String body = EncodingUtil.base64Encode(file) + '\n';
        String body = result + '\n';
        String footer = '--' + separationString + '--';
        String bodyPayload = header + body + footer;
        system.debug('PAYLOAD: ' + bodyPayload);

        HttpRequest req = new HttpRequest();
        req.setHeader('Content-Type', 'multipart/form-data; boundary=' + separationString);
        
        req.setEndpoint(url);
        req.setMethod('POST');
        req.setBody(bodyPayload);
        system.debug('REQUEST: ' + req);

        // Send the request, and return a response
        HttpResponse res = h.send(req);
        System.debug(res.getBody());
        return res.getBody();
    }
}

Help me figure out what mistake is in this code and how to successfully get the file saved in external DB
Best Answer chosen by sukanta Anbu 7
sukanta Anbu 7sukanta Anbu 7
the following is the helper that I have written fr the following scenario:
({
    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 fileContent = objFileReader.result;
            var base64 = 'base64,';
            var dataStart = fileContent.indexOf(base64) + base64.length;
             
            fileContent = fileContent.substring(dataStart);
            // call the uploadProcess method 
            self.uploadProcess(component, file, fileContent);
        });
         
        objFileReader.readAsDataURL(file);
    },
     
    uploadProcess: function(component, file, fileContent) {
        // 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(fileContent.length, startPosition + this.CHUNK_SIZE);
         
        // start with the initial chunk, and set the attachId(last parameter)is null in begin
        this.uploadInChunk(component, file, fileContent, startPosition, endPosition, '');
    },
     
     
    uploadInChunk: function(component, file, fileContent, startPosition, endPosition, attachId) {
        // call the apex method 'SaveFile'
        var getchunk = fileContent.substring(startPosition, endPosition);
        var action = component.get("c.SaveFile");
        action.setParams({
            recordId: component.get("v.recordId"),
            fileName: file.name,
            contentType: file.type,
            file: fileContent
            
        });
         
        // set call back 
        action.setCallback(this, function(response) {
            // store the response / Attachment Id   
            returnValue = response.getReturnValue();
            var state = response.getState();
            if (state === "SUCCESS") {
                // update the start position with end postion
                startPosition = endPosition;
                endPosition = Math.min(fileContent.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, fileContent, startPosition, endPosition, returnValue);
                } 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);
    }
})
Now the file is getting sent via the POST callout without getting saved in the Salesforce standard object

All Answers

David Zhu 🔥David Zhu 🔥
The error is on this line: var fileInput  = component.find("file").getElement();
It seems you are trying to get the file from the input below:
<lightning:input aura:id="fileId" onchange="{!c.handleFilesChange}" type="file" name="file" label="Upload Attachment" multiple="false"/>

In that case, the aura:id should be used, The code would be like this:
var fileInput  = component.find("fileId").getElement();
sukanta Anbu 7sukanta Anbu 7
Hi David,
I want to get the input file. So i have change the code as following. 
  <input aura:id="file" type="file" name="file"></input>
But still I am getting the following error:
[NoErrorObjectAvailable] Script error.
newErrorHandler()@https://static.lightning.force.com/ap16/auraFW/javascript/ozbOZt5SYUotl8he3imvcA/aura_proddebug.js:50227:14
errorHandlerWrapper()@https://static.lightning.force.com/ap16/auraFW/javascript/ozbOZt5SYUotl8he3imvcA/aura_proddebug.js:50243:25
K.dispatchEvent()@https://static.lightning.force.com/ap16/auraFW/javascript/ozbOZt5SYUotl8he3imvcA/aura_proddebug.js:8666:28
K.dispatchChangeEventWithDetail()@https://sukanta02-dev-ed.lightning.force.com/components/lightning/input.js:2:29721
K.dispatchChangeEvent()@https://sukanta02-dev-ed.lightning.force.com/components/lightning/input.js:2:32750
K.handleChange()@https://sukanta02-dev-ed.lightning.force.com/components/lightning/input.js:2:31512
David Zhu 🔥David Zhu 🔥
You may need to modify your code a quite bit. You can refer to this blog: 
http://hellosnl.blogspot.com/2017/08/lightning-component-for-attaching-files.html
The major change points are:

1. add this in html:
<aura:attribute name="fileToBeUploaded" type="Object[]"/>
2. Change:  <input aura:id="file" type="file" name="file" files="{!v.fileToBeUploaded}"></input> 
3. follow method onFileUploaded:function in js controller and upload in helper
4. follow Apex method FileUploadController 
sukanta Anbu 7sukanta Anbu 7
Hi David,
thanks a ton for your help. I will try the above coding. The requirement is that I donot want the file to be saved in sfdc. I just have to pass the file immediately when uploaded to the POST callout to be saved in external database. That is the reason I have not added the 'uploadFile' method in the 'FileUploadController'.  Can you suggest for this scenario? Thanks in advance.
sukanta Anbu 7sukanta Anbu 7
the following is the helper that I have written fr the following scenario:
({
    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 fileContent = objFileReader.result;
            var base64 = 'base64,';
            var dataStart = fileContent.indexOf(base64) + base64.length;
             
            fileContent = fileContent.substring(dataStart);
            // call the uploadProcess method 
            self.uploadProcess(component, file, fileContent);
        });
         
        objFileReader.readAsDataURL(file);
    },
     
    uploadProcess: function(component, file, fileContent) {
        // 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(fileContent.length, startPosition + this.CHUNK_SIZE);
         
        // start with the initial chunk, and set the attachId(last parameter)is null in begin
        this.uploadInChunk(component, file, fileContent, startPosition, endPosition, '');
    },
     
     
    uploadInChunk: function(component, file, fileContent, startPosition, endPosition, attachId) {
        // call the apex method 'SaveFile'
        var getchunk = fileContent.substring(startPosition, endPosition);
        var action = component.get("c.SaveFile");
        action.setParams({
            recordId: component.get("v.recordId"),
            fileName: file.name,
            contentType: file.type,
            file: fileContent
            
        });
         
        // set call back 
        action.setCallback(this, function(response) {
            // store the response / Attachment Id   
            returnValue = response.getReturnValue();
            var state = response.getState();
            if (state === "SUCCESS") {
                // update the start position with end postion
                startPosition = endPosition;
                endPosition = Math.min(fileContent.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, fileContent, startPosition, endPosition, returnValue);
                } 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);
    }
})
Now the file is getting sent via the POST callout without getting saved in the Salesforce standard object
This was selected as the best answer