为使用 google 应用程序脚本和网络应用程序表单上传的所有文件创建一个文件夹

Create one folder for all files uploaded with google apps script and web app form

我有一个带有 GAS 的网络应用程序。此 Web 应用程序具有三个输入(输入 1、输入 2、上传文件输入),两个用于元数据,一个用于上传文件。上传输入是多上传文件输入。当我提交表单时,代码必须为我上传的所有文件生成一个文件夹,并将数据注册在 google sheet 中。例如,我上传文件 1 和文件 2,其中包含文件夹名称的名称或输入 1 的条目。但是,当我转到 google 驱动器时,代码会生成两个同名文件夹,换句话说,例如,两个文件夹,第一个包含文件 1,文件夹名称为“文件夹 1”,第二个文件 2 的文件夹名称为“文件夹 1”。我如何才能为所有文件生成一个文件夹?我的代码有什么问题?你能帮助我吗? 问候! 这是我的代码:

<html>
  <html lang="en">
    <head>
      <meta charset="utf-8" />
      <meta
        name="viewport"
        content="width=device-width, initial-scale=1, shrink-to-fit=no"
      />
      <link
        rel="stylesheet"
        href="https://cdn.jsdelivr.net/npm/bootstrap@4.5.3/dist/css/bootstrap.min.css"
        integrity="sha384-TX8t27EcRE3e/ihU7zmQxVncDAy5uIKz4rEkgIXeMed4M0jlfIDPvg6uqKI2xXr2"
        crossorigin="anonymous"
      />

      <title>TITLE</title>
    </head>
    <body>
      <div class="container">
        <h4>Ingrese datos</h4>
        <div class="form-row">
          <div class="form-group col-sm-6">
            <input
              class="form-control"
              id="numsip"
              type="text"
              placeholder="Set Name for folder"
            />
          </div>
        </div>
        <div class="form-row">
          <div class="form-group col-sm-6">
            <input
              class="form-control"
              id="rut"
              type="number"
              placeholder="Set idnumber"
            />
          </div>
        </div>
        <div class="form-row">
          <div class="form-group col-sm-6">
            <input
              class="form-control"
              id="files"
              type="file"
              placeholder="Seleccione Archivos"
              multiple
            />
          </div>
        </div>
        <button id="contactar" class="btn btn-primary" onclick="enviardatos()">
          Generar carpeta
        </button>
      </div>
      <script
        src="https://code.jquery.com/jquery-3.5.1.slim.min.js"
        integrity="sha384-DfXdz2htPH0lsSSs5nCTpuj/zy4C+OGpamoFVy38MVBnE+IbbVYUew+OrCXaRkfj"
        crossorigin="anonymous"
      ></script>
      <script
        src="https://cdn.jsdelivr.net/npm/bootstrap@4.5.3/dist/js/bootstrap.bundle.min.js"
        integrity="sha384-ho+j7jyWK8fNQe+A12Hb8AhRq26LrZ/JpcUGGOn+Y7RsweNrtN/tE3MoK7ZeZDyx"
        crossorigin="anonymous"
      ></script>
    </body>

    <script>
      function enviardatos() {
        var sip = document.getElementById("numsip");
        var rut = document.getElementById("rut");
        var array = { numsip: sip.value, rut: rut.value };
        const f = document.getElementById("files");
        [...f.files].forEach((file, i) => {
          const fr = new FileReader();
          fr.onload = (e) => {
            const data = e.target.result.split(",");
            const obj = {
              fileName: f.files[i].name,
              mimeType: data[0].match(/:(\w.+);/)[1],
              data: data[1],
            };

            google.script.run
              .withSuccessHandler((id) => {
                console.log(id);
              })
              .addNewRow(array, obj);
          };
          fr.readAsDataURL(file);
        });

        alert("Se ha generado carpeta");
      }
    </script>
  </html>
</html>

这是 google 应用程序脚本的服务器端函数:

function addNewRow(array, obj) {
  var timestamp = new Date();
  var parentFolderId = 'URLPARENTFOLDER';
  var parentFolder = DriveApp.getFolderById(parentFolderId);
  var user = Session.getActiveUser().getEmail();
  var foldercreated = parentFolder.createFolder('SIP ' + array.numsip + '/' + array.rut);
  var idfolder = foldercreated.getId();
  var url = 'URLSHEET';
  var values = SpreadsheetApp.openByUrl(url);
  var ss = values.getSheetByName('DATA');
  ss.appendRow([array.numsip, array.rut, timestamp, user, idfolder]);

  var blob = Utilities.newBlob(Utilities.base64Decode(obj.data), obj.mimeType, obj.fileName);
  return foldercreated.createFile(blob).getId();
}

*我省略了“doGet”函数...

我相信你的目标如下。

  • 您想将上传的文件放到指定的文件夹中。
  • "SIP "+array.numsip+"/"+array.rut 的文件夹名称存在于 parentFolder 中时,您不想创建具有相同文件夹名称的文件夹。您想将文件放入现有文件夹。

修改点:

  • 在这种情况下,我想建议修改 Google Apps Script 端的 addNewRow 和 Javascript 端的 enviardatos() 的功能。
  • 在您当前的脚本中,新文件夹由 var foldercreated = parentFolder.createFolder("SIP "+array.numsip+"/"+array.rut) 每 运行 创建一次。所以这部分需要修改。
    • 检查是否存在同名文件夹。
  • 而且,您的 Google Apps 脚本端,我认为未使用函数底部的 var parentFolder=DriveApp.getFolderById(parentFolderId);
  • 但是,您的脚本中还有更重要的一点。 [...f.files].forEach((file, i) => {,,,})中的脚本是运行的异步处理。这样,即使修改 Google Apps Script 端的脚本,也会创建重复的文件夹名称。所以需要也修改Javascript端的脚本

当以上几点反映到你的脚本中,就会变成如下。请修改addNewRow函数如下

修改后的脚本:

Google Apps 脚本端:

请设置URLPARENTFOLDERURLSHEET

function addNewRow(array,obj) {
  var timestamp = new Date();
  var parentFolderId = "URLPARENTFOLDER";
  var parentFolder = DriveApp.getFolderById(parentFolderId);
  var user = Session.getActiveUser().getEmail();
  var folderName = "SIP "+array.numsip+"/"+array.rut;
  var foldercreated = parentFolder.getFoldersByName(folderName);
  foldercreated = foldercreated.hasNext() ? foldercreated.next() : parentFolder.createFolder(folderName);
  var idfolder= foldercreated.getId()
  var url = "URLSHEET";
  var values = SpreadsheetApp.openByUrl(url);
  var ss= values.getSheetByName("DATA");
  ss.appendRow([array.numsip,array.rut,timestamp,user,idfolder]);
  return obj.map(({fileName, mimeType, data}) => {
    var blob = Utilities.newBlob(Utilities.base64Decode(data), mimeType, fileName);
    return foldercreated.createFile(blob).getId();
  });
}

Javascript 边:

请修改Javascript端的enviardatos()如下。

从:
[...f.files].forEach((file, i) => {
const fr = new FileReader();
fr.onload = (e) => {
  const data = e.target.result.split(",");
  const obj = {fileName: f.files[i].name, mimeType: data[0].match(/:(\w.+);/)[1], data: data[1]};
  
  google.script.run.withSuccessHandler((id) => {console.log(id);}).addNewRow(array, obj);
}
fr.readAsDataURL(file);
});
到:
Promise.all([...f.files].map((file, i) => {
  const fr = new FileReader();
  return new Promise((r, rj) => {
    fr.onload = (e) => {
      const data = e.target.result.split(",");
      r({fileName: f.files[i].name, mimeType: data[0].match(/:(\w.+);/)[1], data: data[1]});
    }
    fr.onerror = (e) => rj(e);
    fr.readAsDataURL(file);
  });
}))
.then(obj => google.script.run.withSuccessHandler(console.log).addNewRow(array, obj))
.catch(err => console.log(err));

参考文献: