Google Apps Script中含文件/图片的表单数据提交至后端函数问题
解决Google Apps Script处理表单图片上传的方案
问题根源
你当前代码的核心错误是google.script.run无法直接传递FormData对象,这是GAS客户端与服务端通信的限制导致的。无需依赖谷歌云,用以下简易方案即可实现图片上传到Drive并关联表单数据。
前端代码修改
将文件转换为Base64格式后,和表单其他数据一起传递:
function saveAlert(){ let out = [] let controls = { alertSelect: document.getElementById('alertSelect'), alertLocation: document.getElementById('alertLocation'), alertCode: document.getElementById('alertCode'), servicesAffected: document.getElementById('servicesAffected'), alertAddress: document.getElementById('alertAddress'), alertSubject: document.getElementById('alertSubject'), alertBody: tinymce.activeEditor.getContent(), alertDate: document.getElementById('alertDate'), alertEndDate: document.getElementById('alertEndDate'), imageUpload: document.getElementById('imageUpload'), userEmail: document.getElementById('userEmail'), } if(validateInput(controls)){ let modalSpinner = document.getElementById('modalSpinner') modalSpinner.hidden = false let alertDateFinal = controls.alertDate.value.replaceAll('-','/') let alertEndDateFinal = controls.alertEndDate.value.replaceAll('-','/') // 处理图片:转换为Base64数组 const imageFiles = []; const fileInput = controls.imageUpload; for (let i = 0; i < fileInput.files.length; i++) { const file = fileInput.files[i]; // 用FileReader读取文件为Base64 const reader = new FileReader(); reader.onload = function(e) { imageFiles.push({ name: file.name, type: file.type, base64: e.target.result.split(',')[1] // 去掉dataURL前缀,只保留Base64内容 }); // 所有文件读取完成后再提交数据 if (imageFiles.length === fileInput.files.length) { submitForm(imageFiles); } }; reader.readAsDataURL(file); } // 如果没有选择图片,直接提交 if (fileInput.files.length === 0) { submitForm([]); } function submitForm(images) { let record = { 'Alert Type': controls.alertSelect.value, 'Alert Location': controls.alertLocation.value, 'Alert Code': controls.alertCode.value, 'Services Affected': controls.servicesAffected.value, 'Alert Address': controls.alertAddress.value, 'Alert Subject': controls.alertSubject.value, 'Alert Details': controls.alertBody, 'Alert Date': alertDateFinal, 'Alert End Date': alertEndDateFinal, 'User Email': controls.userEmail.value, 'Images': images, 'Alert Active': true } out.push(record) google.script.run.withSuccessHandler(clearForm).saveAlerts(out) } } else{ window.alert('Please Check Input') } }
后端代码修改
接收Base64数据,转换为Blob存入Drive,获取文件ID后写入表格:
function saveAlerts(data) { Logger.log(data) // 定义Drive存储文件夹(先在Drive创建好,替换为你的文件夹ID) const folderId = "你的Drive文件夹ID"; const folder = DriveApp.getFolderById(folderId); let sheetData = alerts.getDataRange().getDisplayValues() let keys = sheetData[0] data.forEach(el => { let temp = [] // 处理图片,上传到Drive并获取ID列表 let imageIds = []; el['Images'].forEach(img => { if (img.base64) { // 将Base64转换为Blob const blob = Utilities.newBlob(Utilities.base64Decode(img.base64), img.type, img.name); // 上传到指定文件夹 const file = folder.createFile(blob); // 设置文件权限(可选:让特定用户可查看) file.setSharing(DriveApp.Access.ANYONE_WITH_LINK, DriveApp.Permission.VIEW); imageIds.push(file.getId()); } }); // 替换Images字段为文件ID,用逗号分隔多个ID el['Images'] = imageIds.join(','); keys.forEach(key => { temp.push(el[key]) }) alerts.appendRow(temp) }) let template = HtmlService.createTemplateFromFile('htmlEmail'); template.data = data; template.alertDetails = HtmlService.createHtmlOutput(data[0]['Alert Details']).getContent() // 可选:在邮件中添加图片链接 template.imageLinks = data[0]['Images'].split(',').map(id => `https://drive.google.com/file/d/${id}/view`).join('<br>'); let message = template.evaluate().getContent(); MailApp.sendEmail({ to: 'YOUR EMAIL', subject: `${data[0]['Alert Subject']}`, htmlBody: message, replyTo: `${data[0]['User Email']}` }) }
关键注意事项
- 文件夹ID获取:打开Drive目标文件夹,地址栏中
folders/后面的字符串就是文件夹ID。 - 权限设置:如果需要邮件接收者能查看图片,要设置文件共享权限为“知道链接的人可查看”,代码中已包含该逻辑。
- 文件大小限制:GAS单文件上传最大限制为50MB,若需更大文件需调整方案,但一般图片足够。
内容的提问来源于stack exchange,提问作者Lofton Gentry
相关产品推荐
相关产品推荐

