I have used a Google Apps Script form to upload receipts into Google Drive for a couple of years without problems. A few months ago, files have started to come across as completely blank or corrupted. While a file will appear in Drive, I can't open it or, if it's a PDF, it's the same number of pages but completely blank. Only text files seem to work.
I understand conceptually that I need to add a function to allow the script to process the file on the front end and then pass it to the server (based on this and this). But I can't seem to get the script right because my structure is sufficiently different that it confuses me, frankly.
Here is my form.html:
<!doctype html>
<form id="myForm" align="left">
Your first name: <input type="text" name="myName"><br><br>
<input type="file" name="myFile1"><input type="text" name="myReceipt1" placeholder="Vendor (who was paid)...">
<input type="text" name="myProgram1" placeholder="GenOps, OWP, VSP, etc."><br>
<input type="text" name="myDesc1" placeholder="Expense Desc (e.g. catering, airfare, etc.)" style="width:300px;"><br>
<input type="date" name="myDate1" placeholder="Date Charged (yyyy.mm.dd)" style="width:200px;">
<input type="text" name="myAmt1" placeholder="Amount (dd.cc)"><br>
<input type="file" name="myFile2"><input type="text" name="myReceipt2" placeholder="Vendor (who was paid)...">
<input type="text" name="myProgram2" placeholder="GenOps, OWP, VSP, etc."><br>
<input type="text" name="myDesc2" placeholder="Expense Desc (e.g. catering, airfare, etc.)" style="width:300px;"><br>
<input type="date" name="myDate2" placeholder="Date Charged (yyyy.mm.dd)" style="width:200px;">
<input type="text" name="myAmt2" placeholder="Amount (dd.cc)"><br>
<input type="submit" value="Upload File(s)" style="background-color:#ffd382"
onclick="this.value='Uploading...';
google.script.run.withSuccessHandler(fileUploaded)
.uploadFiles(this.parentNode);
return false;">
</form>
<script>
function fileUploaded(status) {
document.getElementById('myForm').style.display = 'none';
document.getElementById('output').innerHTML = status;
}
</script>
Here is my server.gs:
function doGet(e) {
return HtmlService.createTemplateFromFile('form.html')
.evaluate() // evaluate MUST come before setting the Sandbox mode
.setXFrameOptionsMode(HtmlService.XFrameOptionsMode.ALLOWALL)
.setTitle("AmEx Receipt Upload");8
}
function uploadFiles(form) {
try {
var dropbox = "Receipts"; //name of Drive folder to save uploaded files
var folder, folders = DriveApp.getFoldersByName(dropbox);
if (folders.hasNext()) {
folder = folders.next();
} else {
folder = DriveApp.createFolder(dropbox);
}
var blob = form.myFile1;
var file = folder.createFile(blob);
file.setDescription("Uploaded by " + form.myName);
file.setName(form.myDate1 + "_" + form.myReceipt1 + "_" + form.myProgram1 + "_" + form.myDesc1 + " - " + form.myAmt1);
var blob = form.myFile2;
var file = folder.createFile(blob);
file.setDescription("Uploaded by " + form.myName);
file.setName(form.myDate2 + "_" + form.myReceipt2 + "_" + form.myProgram2 + "_" + form.myDesc2 + " - " + form.myAmt2);
return "Your receipts have been uploaded. Refresh the page if you have more to upload.";
} catch (error) {
return error.toString();
}
}
Any help you can render would be greatly appreciated. It seems that every adjustment I make only makes things worse. If you need me to simply the code snippets more than I have, I certainly can.
Thank you in advance!
In this modification, the file is converted to the byte array and sent to Google Apps Script.
<form id="myForm" align="left">
Your first name: <input type="text" name="myName"><br><br>
<input type="file" name="myFile1">
<input type="text" name="myReceipt1" placeholder="Vendor (who was paid)...">
<input type="text" name="myProgram1" placeholder="GenOps, OWP, VSP, etc."><br>
<input type="text" name="myDesc1" placeholder="Expense Desc (e.g. catering, airfare, etc.)" style="width:300px;"><br>
<input type="date" name="myDate1" placeholder="Date Charged (yyyy.mm.dd)" style="width:200px;">
<input type="text" name="myAmt1" placeholder="Amount (dd.cc)"><br>
<input type="file" name="myFile2">
<input type="text" name="myReceipt2" placeholder="Vendor (who was paid)...">
<input type="text" name="myProgram2" placeholder="GenOps, OWP, VSP, etc."><br>
<input type="text" name="myDesc2" placeholder="Expense Desc (e.g. catering, airfare, etc.)" style="width:300px;"><br>
<input type="date" name="myDate2" placeholder="Date Charged (yyyy.mm.dd)" style="width:200px;">
<input type="text" name="myAmt2" placeholder="Amount (dd.cc)"><br>
<input type="submit" value="Upload File(s)" style="background-color:#ffd382" onclick="submitValues(this);return false;">
</form>
<div id = "output"></div>
<script>
function submitValues(e) {
e.value = 'Uploading...';
const files = [e.parentNode.myFile1.files[0], e.parentNode.myFile2.files[0]];
const object = [...e.parentNode].reduce((o, obj) => Object.assign(o, {[obj.name]: obj.value}), {});
if (files.some(f => f)) {
Promise.all(
files.map(file => new Promise((resolve, reject) => {
if (file) {
const fr = new FileReader();
fr.onload = f => resolve({filename: file.name, mimeType: file.type, bytes: [...new Int8Array(f.target.result)]});
fr.onerror = err => reject(err);
fr.readAsArrayBuffer(file);
} else {
resolve({});
}
}))
).then(ar => {
[object.myFile1, object.myFile2] = ar;
google.script.run.withSuccessHandler(fileUploaded).uploadFiles(object);
});
}
}
function fileUploaded(status) {
document.getElementById('myForm').style.display = 'none';
document.getElementById('output').innerHTML = status;
}
</script>
In this case, uploadFiles
is modified.
function uploadFiles(form) {
try {
var dropbox = "Receipts"; //name of Drive folder to save uploaded files
var folder, folders = DriveApp.getFoldersByName(dropbox);
if (folders.hasNext()) {
folder = folders.next();
} else {
folder = DriveApp.createFolder(dropbox);
}
// --- I modified below script.
var file1 = form.myFile1;
if (Object.keys(file1).length > 0) {
var blob = Utilities.newBlob(file1.bytes, file1.mimeType, file1.filename); // Modified
var file = folder.createFile(blob);
file.setDescription("Uploaded by " + form.myName);
file.setName(form.myDate1 + "_" + form.myReceipt1 + "_" + form.myProgram1 + "_" + form.myDesc1 + " - " + form.myAmt1);
}
var file2 = form.myFile2;
if (Object.keys(file2).length > 0) {
var blob = Utilities.newBlob(file2.bytes, file2.mimeType, file2.filename); // Modified
var file = folder.createFile(blob);
file.setDescription("Uploaded by " + form.myName);
file.setName(form.myDate2 + "_" + form.myReceipt2 + "_" + form.myProgram2 + "_" + form.myDesc2 + " - " + form.myAmt2);
}
// ---
return "Your receipts have been uploaded. Refresh the page if you have more to upload.";
} catch (error) {
return error.toString();
}
}