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

Google Apps Script表单上传图片至Drive时子文件夹重复创建问题

问题修复:Google Apps Script表单上传文件时重复创建子文件夹

你遇到的问题源于两个核心原因:

  • 服务端代码存在变量名拼写错误,导致文件夹查找逻辑异常
  • 多文件上传时,每个文件独立发起服务端请求,并发执行下会重复检测并创建子文件夹

修复步骤及代码修改

1. 修正server.gs中的变量错误与逻辑优化

原代码存在folder和folders变量混用的问题,同时新增单独的文件夹创建/获取函数,避免并发冲突:

function doGet(e) {
  return HtmlService.createHtmlOutputFromFile('forms.html').setTitle("上传文件");
}

// 新增:统一处理用户子文件夹的创建/获取
function getOrCreateUserFolder(name, email) {
  const parentFolderName = "Wedding Pictures";
  // 查找或创建父文件夹
  let parentFolder = DriveApp.getFoldersByName(parentFolderName).next() || DriveApp.createFolder(parentFolderName);
  const subfolderName = `${name} - ${email}`;
  // 查找用户子文件夹,不存在则创建
  const subfolders = parentFolder.getFoldersByName(subfolderName);
  return subfolders.hasNext() ? subfolders.next().getId() : parentFolder.createFolder(subfolderName).getId();
}

function uploadFileToGoogleDrive(data, fileName, folderId) {
  try {
    const contentType = data.substring(5, data.indexOf(';'));
    const bytes = Utilities.base64Decode(data.substr(data.indexOf('base64,') + 7));
    const blob = Utilities.newBlob(bytes, contentType, fileName);
    
    const targetFolder = DriveApp.getFolderById(folderId);
    targetFolder.createFile(blob);
    
    return "OK";
  } catch (error) {
    return error.toString();
  }
}

2. 修改前端代码,先获取文件夹ID再批量上传

将原“逐个文件发起请求”改为“先获取子文件夹ID,再统一上传所有文件”,彻底避免并发创建问题:

<form id="form" style="max-width: 480px;margin: 40px auto;background-color: #fff;padding: 40px;border-radius: 20px;">
  <table style="width: 100%;text-align: center;">
    <tr>
      <td colspan="2">
        <label for="name" style="color: #1a2b56;">Full Name*</label>    
        <input id="name" type="text" name="Name" class="validate" required="" aria-required="true">
      </td>
    </tr>
    <tr>
      <td colspan="2">
        <label for="email" style="color: #1a2b56;">Email Address*</label>
        <input id="email" type="email" name="Email" class="validate" required="" aria-required="true">
      </td>
    </tr>
    <tr>
      <td>
        <div class="upload-btn-wrapper" style="width: 50%;text-align: left;">
          <button class="button">Browse</button>
          <input id="files" type="file" multiple required>
        </div>
      </td>
      <td>
        <input type="text" id="files-chosen" placeholder="Select pictures to upload*" style="padding: 15px 0;margin: 0;text-align: left;width: 100%" disabled>
      </td>
    </tr>
    <tr>
      <td colspan="2">
        <div style="padding: 20px;">
          <button class="button" type="submit" onclick="submitForm();  return false;">Submit</button>
        </div>
      </td>
    </tr>
    <tr>
      <td>        
        <p style="color: red;text-align: left;padding: 15px">* = required</p>
      </td>
    </tr>
    <tr>
      <td colspan="2">
        <p id="progress"></p>
      </td>
    </tr>
  </table>
</form>

<script>
  var a;
  window.fileList = [];
  var filenames = "";
  var input = document.getElementById('files');
  var infoArea = document.getElementById('files-chosen');

  input.addEventListener('change', showFileName);
  
  function showFileName(event) {
    var filenames = "";
    window.fileList = [];
    var input = event.srcElement;

    if (input.files.length == 0){
      alert("Please choose a picture/pictures to upload")
      return false;
    }else{
      for (a=0; a < input.files.length; a++){
        var fileName = input.files[a].name;
        filenames += (a === input.files.length -1) ? fileName : fileName + ", ";
        window.fileList.push(input.files[a]);
      }
      document.getElementById('files-chosen').value=filenames;
    }
  }

  function submitForm(){
    window.complete = 0;
    const fullName = document.getElementById('name').value;
    const emailAdd = document.getElementById('email').value;
    
    alert("Please wait, this may take a while, do not close the page - click OK")
    document.getElementById("progress").innerHTML = window.complete+"/"+window.fileList.length+" uploaded";

    // 先获取子文件夹ID,再批量上传
    google.script.run
      .withSuccessHandler(function(folderId) {
        window.fileList.forEach(function(file){
          sendFile(file, folderId);
        });
      })
      .getOrCreateUserFolder(fullName, emailAdd);
  }

  sendFile = function(file, folderId){
    var reader = new FileReader();
    reader.onloadend = function(e) {
      google.script.run
        .withSuccessHandler(successShow)
        .uploadFileToGoogleDrive(e.target.result, file.name, folderId);
    };
    reader.readAsDataURL(file);
  }

  function successShow(e){
    if (e === "OK"){
      window.complete++;
      document.getElementById("progress").innerHTML = window.complete+"/"+window.fileList.length+" uploaded";
    }
    if (window.complete == window.fileList.length){
      alert("Pictures uploaded successfully");
      document.getElementById("form").reset();
      document.getElementById("progress").innerHTML = "";
    }
  }

  function reset() {
    document.getElementById("form").reset();
    document.getElementById("progress").innerHTML = "";
  }
</script>

修复说明

  • 变量名修正:解决原server.gs中folder与folders混用的逻辑错误,确保文件夹查找正常
  • 并发冲突解决:通过先统一获取/创建子文件夹ID,再批量上传文件的方式,避免多个请求同时检测文件夹状态导致的重复创建问题

内容的提问来源于stack exchange,提问作者mdavies

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.26 22:28:18