need some help :)
my code is supposed to delete the contents of a folder, and then, and only then, take the input from a file selector and have those new files uploaded to the folder that was emptied previously.
the problem:
It looks like the sendFileToDrive is executed somehow on the server side at the same time that the folder gets emptied also on the server side so some files remain in the google drive and some others get deleted by the time the whole file set is uploaded to google drive.
The solution (UPDATED):
As per @TheAddonDepot and also @NaziA's suggestion: I moved my upload code to the function executed with withSuccessHandler so only once the folder is cleared on the server-side, my upload code takes care of the uploading without having any folder clearing happening asynchronously (in paralell) at the same time.
here's my code (updated and working :)):
html
<!DOCTYPE html>
<html>
<head>
<!--<base target="_parent"> -->
<!--Let browser know website is optimized for mobile-->
<meta name="viewport" content="width=device-width, initial-scale=1.0"/>
<!--Import Google Icon Font-->
<link href="https://fonts.googleapis.com/icon?family=Material+Icons" rel="stylesheet">
<!-- Compiled and minified CSS -->
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/materialize/1.0.0/css/materialize.min.css">
</head>
<body class = "container">
<form class = "col s12">
<!-- File Upload Form Component STARTS-->
<div class = "row">
<div class="file-field input-field">
<div class="btn">
<span>Browse</span>
<input type="file" accept=".csv" id="fileSelector" multiple> <!-- input for file and attribute to allow multiple upload -->
</div>
<div class="file-path-wrapper">
<input class="file-path validate" type="text" placeholder="Upload one or more csv files">
</div>
<a class="waves-effect waves-light btn-small" id="upload">Upload Files</a>
</div>
</div>
<!-- File Upload Form Component ENDS-->
<!-- show files uploaded STARTS -->
<div id="output" style="text-align:center;"></div>
<!-- show files uploaded ENDS -->
</form>
<script src="https://cdnjs.cloudflare.com/ajax/libs/materialize/1.0.0-beta/js/materialize.min.js"></script>
<?!= include("uploadFiles_js"); ?>
</body>
</html>
my js
//crear a event listerner for upload button to execute a function when clicked
var uploadButton = document.getElementById('upload');
uploadButton.addEventListener("click", handleFiles, false);
//function triggered when the file form component is changed
function handleFiles(){
try{
//remove the files in the target folder
google.script.run.withSuccessHandler(filesRemoved)
.withFailureHandler(failOnServerSide)
.clearTargetFolder();
}catch(e){
alert("error in handleFiles" + e.toString());
}
}
//this function receives the number of files removed
//on destination folde prior the upload and attempts the upload
//once the removal of files is completed
function filesRemoved (numberOfFilesRemoved){
try{
filesRemovedOnDestinationFolder = numberOfFilesRemoved;
//grab the files from file iterator in to a files list variable
var fileList = document.getElementById('fileSelector').files;
//update variable to show files to upload
filesToUpload = fileList.length;
//for every file in the filelist...
for (let i = 0; i < fileList.length; i++){
//grab the individual file
var file = fileList[i];
//if the file has a file name
if (file.name != ""){
//save file to Drive
sendFileToDrive(file);
}
}
}catch(e){
alert("error in filesRemoved" + e.toString());
}
}
//function to read and execute for each file to save/upload to google drive
function sendFileToDrive(file) {
try{
//create a reader
var reader = new FileReader();
//when upload event occurs...
reader.onload = function (e) {
//create an fileObj to upload to gdrive
//withe 3 object components to create file in gdrive from blob
//var blob = Utilities.newBlob(fileObj.fileContent, fileObj.fileType, fileObj.fileName);
const fileObj = {
fileName: file.name,
fileType: file.type,
fileContent: e.target.result //this apparently the same as reader.result
}
//send the fileObj to saveFile server side function
google.script.run.withSuccessHandler(uploadResults)
.withFailureHandler(failOnServerSide)
.saveFile(fileObj);
};
// this reader method seems to work to read the csv files
//which is key to get the file content
reader.readAsBinaryString(file);
}catch(e){
alert("error in sendFileToDrive"+ e.toString());
}
}
my gs code
function saveFile(fileObj){
try{
//Logger.log('fileObj.fileContent: '+ fileObj.fileContent);
//make a blob out of the file object so a file can be created with it in google drive
var blob = Utilities.newBlob(fileObj.fileContent, fileObj.fileType, fileObj.fileName);
//get the folder
var folder = DriveApp.getFolderById(targetFolderID);
//Let's create the file, got from the form, within the folder.
var file = folder.createFile(blob);
SpreadsheetApp.flush();
//Let's return the file's url
return file.getUrl();
//return "this is the file name received at saveFile in GS: "+ fileName;
}catch(e){
Logger.log('e: ' + e.toString());
return "error in gs saveFile: "+ e.toString();
}
}
//function that clears the contents of the target folder
//target folder id is defined as a global variable outside function
function clearTargetFolder(){
//files removed (return variable)
var filesTrashed = 0;
//get folder
var folder = DriveApp.getFolderById(targetFolderID); //targetFolderID global variable defined at top
//get files iterator from folder
var filesInFolder = folder.getFiles();
//for each file in folder...
while(filesInFolder.hasNext()){
//get file
var file = filesInFolder.next();
//set it to trash
file.setTrashed(true);
//update filesTrashed variable
filesTrashed = filesTrashed + 1;
}
//return totals files trashed
return filesTrashed;
}