React+Google Apps Script Web应用Google Drive文件上传异常求助
问题根源与解决方案
问题原因
你的代码存在两个核心问题:
- React文件输入处理错误:
type="file"的输入框中,e.target.value仅返回本地文件路径字符串,而非实际的File对象,导致传给Google Apps Script(GAS)的是无效路径,无法生成Blob上传到Drive。 - 数据传递方式不兼容:
google.script.run无法直接序列化并传递浏览器端的File对象,而原生JS环境下你大概率用了FormData直接提交到GAS的doPost接口,这才是文件上传的正确方式。
修复步骤
1. 调整React组件(App.js)
修改文件输入的处理逻辑,改用FormData结合fetch提交表单,和原生JS的工作方式保持一致:
import React from "react"; import { useState } from "react"; export default function App () { const [formData, setFormData] = useState({ email: "", firstname: "", screenShot: null }) const handleInputChange = (e) => { const { name, value } = e.target; setFormData({ ...formData, [name]: value }); }; // 单独处理文件输入,存储File对象 const handleFileChange = (e) => { setFormData({ ...formData, screenShot: e.target.files[0] }); }; const handleSubmit = async (e) => { e.preventDefault(); const submitData = new FormData(); submitData.append('email', formData.email); submitData.append('firstname', formData.firstname); if (formData.screenShot) { submitData.append('screenShot', formData.screenShot); } try { await fetch(window.location.href, { method: 'POST', body: submitData }); alert('提交成功'); // 重置表单状态 setFormData({ email: "", firstname: "", screenShot: null }); document.querySelector('input[type="file"]').value = ""; } catch (err) { console.error('提交失败:', err); alert('提交失败,请重试'); } } return ( <> <form onSubmit={handleSubmit}> <input className="form-control form-control-sm" name="email" type="email" value={formData.email} onChange={handleInputChange} placeholder="Email" required /> <input className="form-control form-control-sm" name="firstname" type="text" value={formData.firstname} onChange={handleInputChange} placeholder="First Name" required /> <input className="form-control-file" type="file" name="screenShot" onChange={handleFileChange} placeholder="Upload Screenshot" /> <button type="submit" className="btn btn-primary mt-2">提交</button> </form> </> ); }
2. 更新GAS后端(Code.gs)
添加doPost函数处理FormData提交,同时修正原doGet中的meta标签笔误:
const SheetURL = "https://docs.google.com/spreadsheets/d/1-zrE_wEoNFaFuGh_9CBvy6shqIBNhaaoML875BLnUxQ/edit#gid=165730349"; const SS = SpreadsheetApp.openByUrl(SheetURL); const WorkSheet = SS.getSheetByName('Portal Responses'); const FOLDER_ID = "191THLqPpVIT-1Pdj1ylm1QEskOtV31HD"; function doGet() { return HtmlService.createTemplateFromFile('index').evaluate() .addMetaTag("viewport", "width=device-width, initial-scale=1.0") // 修正笔误:data.device-width → device-width } // 处理FormData提交的核心函数 function doPost(e) { try { const formParams = e.parameter; // 获取上传的文件(如果存在) const uploadedFile = e.files?.screenShot?.[0]; let fileUrl = "No File Uploaded"; if (uploadedFile) { const targetFolder = DriveApp.getFolderById(FOLDER_ID); const driveFile = targetFolder.createFile(uploadedFile); driveFile.setDescription(`Uploaded by ${formParams.firstname}`); fileUrl = driveFile.getUrl(); } // 写入Google Sheet const rowData = [ new Date(), formParams.email, formParams.firstname, fileUrl ]; WorkSheet.appendRow(rowData); return ContentService.createTextOutput(JSON.stringify({ success: true })) .setMimeType(ContentService.MimeType.JSON); } catch (error) { return ContentService.createTextOutput(JSON.stringify({ success: false, error: error.message })) .setMimeType(ContentService.MimeType.JSON); } }
额外说明
- 原
appendEntry函数依赖google.script.run传递Blob,但由于File对象无法序列化,该方式不适用,改用doPost处理FormData是更可靠的方案。 - 确保你的GAS项目已部署为Web应用,且部署选项中“谁可以访问此应用”设置正确,同时允许POST请求。
内容的提问来源于stack exchange,提问作者Kuldeep Singh
相关产品推荐
相关产品推荐

