Skip to content

Instantly share code, notes, and snippets.

@peterknolle
Last active January 30, 2023 20:40
  • Star 19 You must be signed in to star a gist
  • Fork 11 You must be signed in to fork a gist
Star You must be signed in to star a gist
Save peterknolle/bb4b7ac63f67f66c32b0 to your computer and use it in GitHub Desktop.
Lightning File Upload Component
public class FileController {
@AuraEnabled
public static Id saveTheFile(Id parentId, String fileName, String base64Data, String contentType) {
base64Data = EncodingUtil.urlDecode(base64Data, 'UTF-8');
Attachment a = new Attachment();
a.parentId = parentId;
a.Body = EncodingUtil.base64Decode(base64Data);
a.Name = fileName;
a.ContentType = contentType;
insert a;
return a.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');
Attachment a = [
SELECT Id, Body
FROM Attachment
WHERE Id = :fileId
];
String existingBody = EncodingUtil.base64Encode(a.Body);
a.Body = EncodingUtil.base64Decode(existingBody + base64Data);
update a;
}
}
<!-- fileUpload2.cmp is identical -->
<aura:component controller="paura.FileController">
<aura:attribute name="parentId" type="Id"/>
<aura:handler event="aura:waiting" action="{!c.waiting}"/>
<aura:handler event="aura:doneWaiting" action="{!c.doneWaiting}"/>
<div class="container">
<input type="file" class="file" aura:id="file" />
<ui:button label="Save" press="{!c.save}"/>
<div aura:id="uploading" class="notUploading">
<img src="/resource/paura__images/loading-gray.gif" alt="uploading" class="small-spinner" /> Uploading...
</div>
</div>
</aura:component>
/* fileUpload2.css is identical */
.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;
}
/* fileUploadController2.js is identical */
({
save : function(component, event, helper) {
helper.save(component);
},
waiting: function(component, event, helper) {
$A.util.addClass(component.find("uploading").getElement(), "uploading");
$A.util.removeClass(component.find("uploading").getElement(), "notUploading");
},
doneWaiting: function(component, event, helper) {
$A.util.removeClass(component.find("uploading").getElement(), "uploading");
$A.util.addClass(component.find("uploading").getElement(), "notUploading");
}
})
({
MAX_FILE_SIZE: 750 000, /* 1 000 000 * 3/4 to account for base64 */
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 action = component.get("c.saveTheFile");
action.setParams({
parentId: component.get("v.parentId"),
fileName: file.name,
base64Data: encodeURIComponent(fileContents),
contentType: file.type
});
action.setCallback(this, function(a) {
attachId = a.getReturnValue();
console.log(attachId);
});
$A.run(function() {
$A.enqueueAction(action);
});
}
})
({
MAX_FILE_SIZE: 4 500 000, /* 6 000 000 * 3/4 to account for base64 */
CHUNK_SIZE: 950 000, /* 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) {
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) {
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);
}
});
$A.run(function() {
$A.enqueueAction(action);
});
}
})
<!-- This is a simple app that shows how the component can be used.
The Id could be passed in via URL or some other mechanism.
This is just for testing.
-->
<aura:application>
<div class="container">
<!--<paura:fileUpload parentId="0013020s006DqaI"/>-->
<paura:fileUpload2 parentId="0013020s006DqaI"/>
</div>
</aura:application>
@vijaykumar8448
Copy link

How can we add a file which have file size 10 MB?

@vijaykumar8448
Copy link

HI Peter , How can we add a file which have file size 10 MB?

@lushang
Copy link

lushang commented Mar 23, 2017

The code has two places to update BEFORE YOU USE IT:

  1. Change CHUNK_SIZE to a smaller number:
    CHUNK_SIZE: 450 000, /* Use a multiple of 4 */

  2. Add $A.getCallback() to the async file reader onload event:

    fr.onload = $A.getCallback(function() {
            var fileContents = fr.result;
    	    var base64Mark = 'base64,';
            var dataStart = fileContents.indexOf(base64Mark) + base64Mark.length;

            fileContents = fileContents.substring(dataStart);
       
    	    self.upload(component, file, fileContents);
        });
  1. Delete $A.run() since it's not supported anymore

Change

    $A.run(function() {
            $A.enqueueAction(action); 
        });

TO
$A.enqueueAction(action);

@johnc847
Copy link

How can I make the user load attachments when using this on a form?

@pvnjoy00
Copy link

why do you have 2 helper classes?

@Vickal
Copy link

Vickal commented Jun 25, 2017

I'm getting below error on save.
'TypeError: $A.run is not a function[Learn More] safeEval.html:63:9
VIC$FileUploadCompt.helper.upload components/VIC/FileUploadCompt.js:63:9
VIC$FileUploadCompt.helper.save/fr.onload'
Any Idea ?

@arun12209
Copy link

Hi @lushang, I have implemented this code to upload file size upto 4mb. But when i trying to upload file size 1.3mb getting error
'Input too long. [1, 173]' . Can you please help.

@rajanr1021
Copy link

Hi @lushang, After attachments are uploading twice for me after double clicking the save button.If i click once the save button i did not see anything is uploaded.Can you please assist on your code??

@badrianth
Copy link

hey iam getting below error please rectify........
aura_proddebug.js:24605 Uncaught TypeError: Cannot read property 'upload' of undefined
throws at components/c/upload.js:24:15 TypeError: Cannot read property 'upload' of undefined
at FileReader.fr.onload (components/c/upload.js:24)

@Satya738
Copy link

Satya738 commented Nov 9, 2018

Hi Peter

How can we change the code to upload larger files. like 10 to 20MB files. I have tried increasing the MAX_FILE_SIZE but not worked for me. Getting below error. Please help me with uploading the larger files.

fileuploadissue

@RuntimeMendes
Copy link

o erro ainda continua

@RanaForam
Copy link

Hi @peterknolle @Satya738

How can we modify the code to upload a 10 MB file ?

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment