自定义HTML表单提交至Google Sheet/Drive失败,遇CORS错误求助
解决Google Apps Script Web App的CORS错误及文件上传问题
核心问题原因
浏览器发送POST请求前会先发起OPTIONS预检请求,你的Google Apps Script未处理该请求,也未返回CORS允许头,导致浏览器拦截响应。即便权限设为“任何人”,也需要明确处理预检请求并配置正确的响应头。
步骤1:修正Google Apps Script代码(处理CORS与文件上传)
更新doPost函数,添加OPTIONS请求处理逻辑,并正确解析表单上传的文件:
function doPost(e) { // 处理CORS预检请求 if (e.method === 'OPTIONS') { return ContentService.createTextOutput('') .setMimeType(ContentService.MimeType.TEXT) .setHeaders({ 'Access-Control-Allow-Origin': '*', 'Access-Control-Allow-Methods': 'POST, OPTIONS', 'Access-Control-Allow-Headers': 'Content-Type' }); } try { // 提取表单文本字段 const email = e.parameters.email[0]; const name = e.parameters.name[0]; // 提取上传的文件(FormData上传的文件以Blob形式存在) const stlBlob = e.parameters.stlFile[0]; const idCardBlob = e.parameters.idCardFile[0]; // 写入Google Sheet const targetSheet = SpreadsheetApp.openById('你的Google Sheet ID') .getSheetByName('表单数据'); // 替换为你的工作表名称 targetSheet.appendRow([email, name, new Date()]); // 保存文件到Google Drive const targetFolder = DriveApp.getFolderById('你的Drive文件夹ID'); // 保存STL文件 if (stlBlob) { targetFolder.createFile(stlBlob); } // 保存学生证文件 if (idCardBlob) { targetFolder.createFile(idCardBlob); } // 返回成功响应(带CORS头) return ContentService.createTextOutput(JSON.stringify({ status: 'success', message: '数据与文件已成功保存' })) .setMimeType(ContentService.MimeType.JSON) .setHeaders({ 'Access-Control-Allow-Origin': '*' }); } catch (err) { // 返回错误响应(带CORS头) return ContentService.createTextOutput(JSON.stringify({ status: 'error', message: err.toString() })) .setMimeType(ContentService.MimeType.JSON) .setHeaders({ 'Access-Control-Allow-Origin': '*' }); } }
步骤2:重新部署Web App(关键配置)
- 在Google Apps Script编辑器中,点击部署 > 新部署
- 类型选择Web应用
- 执行权限:选择任何人,甚至匿名(必须选此项,否则匿名请求会被拦截)
- 访问权限:选择任何人
- 点击部署,复制生成的Web App URL,替换前端代码中的旧URL
步骤3:修正前端表单提交代码
用FormData处理文件上传,避免设置mode: 'no-cors':
<form id="submissionForm"> <label>邮箱:<input type="email" name="email" required></label> <label>姓名:<input type="text" name="name" required></label> <label>STL文件:<input type="file" name="stlFile" accept=".stl" required></label> <label>学生证:<input type="file" name="idCardFile" required></label> <button type="submit">提交</button> </form> <script> document.getElementById('submissionForm').addEventListener('submit', async (evt) => { evt.preventDefault(); const formData = new FormData(evt.target); try { const response = await fetch('你的Web App URL', { method: 'POST', body: formData }); const result = await response.json(); console.log(result); alert('提交成功!'); } catch (error) { console.error('提交失败:', error); alert('提交失败,请检查控制台信息或重试'); } }); </script>
常见问题排查
- 若仍报错,检查Web App是否部署了新版本(草稿版本不会生效)
- 确认Google Sheet和Drive文件夹的权限:脚本执行账号需要拥有编辑权限
- 不要在fetch中添加
mode: 'no-cors',这会导致无法读取响应,还可能隐藏实际错误
内容的提问来源于stack exchange,提问作者Abhishek Sagar
相关产品推荐
相关产品推荐

