You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

React+Google Apps Script Web应用Google Drive文件上传异常求助

问题根源与解决方案

问题原因

你的代码存在两个核心问题:

  1. React文件输入处理错误:type="file"的输入框中,e.target.value仅返回本地文件路径字符串,而非实际的File对象,导致传给Google Apps Script(GAS)的是无效路径,无法生成Blob上传到Drive。
  2. 数据传递方式不兼容: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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.23 06:09:50