This post explains how to use custom multiple file upload in Lightning web components(lwc).
Note:
This component only works for small size files, it will not work for the big size files.
customMulitipleFileUploader.html
<template>
<lightning-card title="Custom Multiple File Uploader In LWC">
<div style="margin-left:4%">
<div>
<lightning-input type="file"
label=""
onchange={handleFileChanges}
multiple>
</lightning-input>
</div>
<div if:true={fileNames} class="slds-text-body_small slds-text-color_error">{fileNames}
<template if:true={showLoadingSpinner}>
<lightning-spinner alternative-text="Uploading......" size="medium"></lightning-spinner>
</template>
</div><br />
<lightning-button class="slds-m-top--medium"
label="Upload Files"
onclick={handleSaveFiles}
variant="brand">
</lightning-button>
</div><br />
<template if:true={data}>
<lightning-card title="Uploaded Files" icon-name="standard:account">
<div style="width: auto;">
<lightning-datatable data={data}
columns={columns}
key-field="id">
</lightning-datatable>
</div>
</lightning-card>
</template>
</lightning-card>
</template>
customMulitipleFileUploader.jsimport {LightningElement, track} from 'lwc';
import saveFiles from '@salesforce/apex/GenericController.saveFiles';
import getFiles from '@salesforce/apex/GenericController.returnFiles';
import {ShowToastEvent} from 'lightning/platformShowToastEvent';
const columns = [{
label: 'Title',
fieldName: 'FileName',
type: 'url',
typeAttributes: {
label: {
fieldName: 'Title'
},
target: '_blank'
}
}];
export default class CustomMulitipleFileUploader extends LightningElement {
showLoadingSpinner = false;
@track fileNames = '';
@track filesUploaded = [];
@track data;
@track columns = columns;
handleFileChanges(event) {
let files = event.target.files;
if (files.length > 0) {
let filesName = '';
for (let i = 0; i < files.length; i++) {
let file = files[i];
filesName = filesName + file.name + ',';
let freader = new FileReader();
freader.onload = f => {
let base64 = 'base64,';
let content = freader.result.indexOf(base64) + base64.length;
let fileContents = freader.result.substring(content);
this.filesUploaded.push({
Title: file.name,
VersionData: fileContents
});
};
freader.readAsDataURL(file);
}
this.fileNames = filesName.slice(0, -1);
}
}
handleSaveFiles() {
this.showLoadingSpinner = true;
saveFiles({filesToInsert: this.filesUploaded})
.then(data => {
this.showLoadingSpinner = false;
const showSuccess = new ShowToastEvent({
title: 'Success!!',
message: this.fileNames + ' files uploaded successfully.',
variant: 'Success',
});
this.dispatchEvent(showSuccess);
this.getFilesData(data);
this.fileNames = undefined;
})
.catch(error => {
const showError = new ShowToastEvent({
title: 'Error!!',
message: 'An Error occur while uploading the file.',
variant: 'error',
});
this.dispatchEvent(showError);
});
}
getFilesData(lstIds) {
getFiles({lstFileIds: lstIds})
.then(data => {
data.forEach((record) => {
record.FileName = '/' + record.Id;
});
this.data = data;
})
.catch(error => {
window.console.log('error ====> ' + error);
})
}
}
customMulitipleFileUploader.js.meta-xml<?xml version="1.0" encoding="UTF-8"?>
<LightningComponentBundle xmlns="http://soap.sforce.com/2006/04/metadata">
<apiVersion>48.0</apiVersion>
<isExposed>true</isExposed>
<targets>
<target>lightning__AppPage</target>
<target>lightning__RecordPage</target>
<target>lightning__HomePage</target>
<target>lightning__Tab</target>
</targets>
</LightningComponentBundle>
Apex Class
public inherited sharing class GenericController {
@AuraEnabled
public static list<ContentVersion> returnFiles(list<String> lstFileIds){
return [SELECT Id, Title FROM ContentVersion WHERE Id IN :lstFileIds];
}
@AuraEnabled
public static list<Id> saveFiles(list<Object> filesToInsert){
list<Id> lstCntVerIds = new list<Id>();
List<ContentVersion> lstVersionsToInsert = new List<ContentVersion>();
for (Object file : filesToInsert) {
FileInfo fileData = (FileInfo)JSON.deserialize(JSON.serialize(file), FileInfo.class);
ContentVersion objCntVersion = new ContentVersion();
objCntVersion.PathOnClient = fileData.Title;
objCntVersion.Title = fileData.Title;
objCntVersion.VersionData = fileData.VersionData;
lstVersionsToInsert.add(objCntVersion);
}
list<Database.saveResult> res = Database.insert(lstVersionsToInsert);
for (Database.SaveResult saveResult : res) {
if(saveResult.isSuccess()) {
lstCntVerIds.add(saveResult.getId());
}
}
return lstCntVerIds;
}
public class FileInfo {
public String Title;
public Blob VersionData;
}
}
Output