I am developing a lightning component to upload files in the contentVersion object. I used this site as a reference:
http://peterknolle.com/file-upload-lightning-component/
I was able to successfully upload files up to 4 MB without chunking but I am facing an issue with large files(Size > 4MB).
Whenever I upload the file , it gives me the following error :
System.StringException: Unrecognized base64 character: %
I am attaching the code for my helper class and apex controller.
Helper Class :
({
MAX_FILE_SIZE: 4 500 000, /* 6 000 000 * 3/4 to account for base64 */
CHUNK_SIZE: 950 000, /* Use a multiple of 4 */
readFile: function(component, helper, file) {
if (!file) return;
var reader = new FileReader();
self = this;
reader.onload = function() {
var dataURL = reader.result;
component.set("v.pictureSrc", "https://s3-us-west-1.amazonaws.com/sfdc-demo/image-placeholder.png");
self.upload(component, file, dataURL);
};
reader.readAsDataURL(file);
},
upload: function(component, file, dataURL) {
console.log('uploading file ...');
var fromPos = 0;
var toPos = Math.min(dataURL.length, fromPos + this.CHUNK_SIZE);
console.log('toPos '+toPos);
console.log(' fromPos '+fromPos);
this.uploadChunk(component, file, dataURL, fromPos, toPos,'');
},
uploadChunk : function(component, file, dataURL, fromPos, toPos,contentDocumentId){
console.log('uploading chunk ');
var action = component.get("c.saveTheChunkChatterFile");
var chunk = dataURL.substring(fromPos, toPos);
console.log(chunk);
action.setParams({
parentId: component.get("v.recordId"),
fileName: file.name,
base64Data: encodeURIComponent(chunk),
contentType: file.type,
contentDocumentId :contentDocumentId
});
var self = this;
action.setCallback(this, function(a) {
contentDocumentId = a.getReturnValue();
console.log('return value '+contentDocumentId);
fromPos = toPos;
toPos = Math.min(dataURL.length, fromPos + self.CHUNK_SIZE);
if (fromPos < toPos) {
self.uploadChunk(component, file, dataURL, fromPos, toPos, contentDocumentId);
}else{
component.set("v.message", "File Uploaded");
}
});
component.set("v.message", "Uploading...");
$A.enqueueAction(action);
}
})
Apex Controller :
@AuraEnabled
public static Id saveChatterFiles(Id parentId, String fileName, String base64Data, String contentType) {
system.debug('Saving chatter files '+fileName + ' '+ contentType);
ContentVersion testContentInsert =new ContentVersion();
testContentInsert.Title =fileName;
testContentInsert.VersionData=EncodingUtil.base64Decode(base64Data);
testContentInsert.PathOnClient='/' + fileName ;
insert testContentInsert;
system.debug('testContentInsert.id '+ testContentInsert.id);
testContentInsert = [select id, ContentDocumentId from ContentVersion WHERE Id =: testContentInsert.Id];
ContentDocumentLink cl = new ContentDocumentLink();
cl.ContentDocumentId = testContentInsert.ContentDocumentId;
cl.LinkedEntityId = parentId;
cl.ShareType = 'V';
cl.Visibility = 'AllUsers';
insert cl;
system.debug('testContentInsert.id');
return testContentInsert.id;
}
@AuraEnabled
public static Id saveTheChunkChatterFile(id parentId,String fileName, String base64Data, String contentType, String contentDocumentId){
system.debug('saving chatter file');
if (contentDocumentId == '' || contentDocumentId==null ) {
system.debug('null id');
contentDocumentId = saveChatterFiles(parentId, fileName, base64Data, contentType);
} else {
system.debug('not null id');
system.debug('id '+contentDocumentId);
appendToFileChatter(contentDocumentId, base64Data);
}
return Id.valueOf(contentDocumentId);
}
@AuraEnabled
public static void appendToFileChatter(Id contentDocumentId, String base64Data) {
base64Data = EncodingUtil.urlDecode(base64Data, 'UTF-8');
system.debug('appending');
ContentVersion a = [
SELECT Id, VersionData,ContentDocumentId
FROM ContentVersion
WHERE Id = :contentDocumentId
];
String existingBody = EncodingUtil.base64Encode(a.VersionData);
a.VersionData = EncodingUtil.base64Decode(existingBody + base64Data);
update a;
}
My aim is to upload large files(size > 10MB ) using a lightning component. Are there any alternative solutions?