google-apps-script - Google Apps 脚本正在损坏/删除通过我创建的表单上传的所有文件。我该如何解决?

标签 google-apps-script file-upload web-applications

几年来,我一直使用 Google Apps 脚本表单将收据上传到 Google 云端硬盘,没有出现任何问题。几个月前,文件开始显得完全空白或损坏。虽然文件会出现在云端硬盘中,但我无法打开它,或者,如果它是 PDF,它的页数相同,但完全空白。似乎只有文本文件才有效。

我从概念上理解,我需要添加一个函数来允许脚本在前端处理文件,然后将其传递到服务器(基于 thisthis )。但坦率地说,我似乎无法正确编写脚本,因为我的结构非常不同,这让我感到困惑。

这是我的form.html:

    <!doctype html>
     <form id="myForm" align="left">
            Your first name: <input type="text" name="myName"><br><br>
            <input type="file" name="myFile1"><input type="text" name="myReceipt1" placeholder="Vendor (who was paid)...">
            <input type="text" name="myProgram1" placeholder="GenOps, OWP, VSP, etc."><br>
            <input type="text" name="myDesc1" placeholder="Expense Desc (e.g. catering, airfare, etc.)" style="width:300px;"><br>
            <input type="date" name="myDate1" placeholder="Date Charged (yyyy.mm.dd)" style="width:200px;">
            <input type="text" name="myAmt1" placeholder="Amount (dd.cc)"><br>
            
            <input type="file" name="myFile2"><input type="text" name="myReceipt2" placeholder="Vendor (who was paid)...">
            <input type="text" name="myProgram2" placeholder="GenOps, OWP, VSP, etc."><br>
            <input type="text" name="myDesc2" placeholder="Expense Desc (e.g. catering, airfare, etc.)" style="width:300px;"><br>
            <input type="date" name="myDate2" placeholder="Date Charged (yyyy.mm.dd)" style="width:200px;">
            <input type="text" name="myAmt2" placeholder="Amount (dd.cc)"><br>

            
            <input type="submit" value="Upload File(s)" style="background-color:#ffd382"
            
            onclick="this.value='Uploading...';
                    google.script.run.withSuccessHandler(fileUploaded)
                    .uploadFiles(this.parentNode);
                    return false;">
     </form>

<script>
    function fileUploaded(status) {
        document.getElementById('myForm').style.display = 'none';
        document.getElementById('output').innerHTML = status;
    }
</script>
     

这是我的server.gs:

function doGet(e) {
    return HtmlService.createTemplateFromFile('form.html')
        .evaluate() // evaluate MUST come before setting the Sandbox mode
        .setXFrameOptionsMode(HtmlService.XFrameOptionsMode.ALLOWALL)
        .setTitle("AmEx Receipt Upload");8       
}

function uploadFiles(form) {
  
  try {
    
    var dropbox = "Receipts";  //name of Drive folder to save uploaded files
    var folder, folders = DriveApp.getFoldersByName(dropbox);
    
    if (folders.hasNext()) {
      folder = folders.next();
    } else {
      folder = DriveApp.createFolder(dropbox);
    }
    
    var blob = form.myFile1;
    var file = folder.createFile(blob);    
    file.setDescription("Uploaded by " + form.myName);
    file.setName(form.myDate1 + "_" + form.myReceipt1 + "_" + form.myProgram1 + "_" + form.myDesc1 + " - " + form.myAmt1);
    
    var blob = form.myFile2;    
    var file = folder.createFile(blob);    
    file.setDescription("Uploaded by " + form.myName);
    file.setName(form.myDate2 + "_" + form.myReceipt2 + "_" + form.myProgram2 + "_" + form.myDesc2 + " - " + form.myAmt2);

    return "Your receipts have been uploaded. Refresh the page if you have more to upload.";
    
  } catch (error) { 
    return error.toString();
  }      
}

如果您能提供任何帮助,我们将不胜感激。似乎我所做的每一次调整都只会让事情变得更糟。如果您需要我比我更简单地提供代码片段,我当然可以。

提前谢谢您!

最佳答案

修改点:

  • 我认为上传文件损坏的问题可能与 this thread 相同。 .
  • 为了避免损坏上传的文件,例如,需要将文件转换为字节数组和 Base64,然后发送到 Google Apps 脚本。
  • 但是当我看到你的脚本时,我认为为了使用上面的内容,需要发送2个文件和几个值,并且需要修改Javascript和Google Apps脚本。我想这可能有点复杂。所以我提出修改后的脚本作为答案。

修改后的脚本:

在此修改中,文件将转换为字节数组并发送到 Google Apps 脚本。

HTML&Javascript 方面:

<form id="myForm" align="left">
Your first name: <input type="text" name="myName"><br><br>
<input type="file" name="myFile1">
<input type="text" name="myReceipt1" placeholder="Vendor (who was paid)...">
<input type="text" name="myProgram1" placeholder="GenOps, OWP, VSP, etc."><br>
<input type="text" name="myDesc1" placeholder="Expense Desc (e.g. catering, airfare, etc.)" style="width:300px;"><br>
<input type="date" name="myDate1" placeholder="Date Charged (yyyy.mm.dd)" style="width:200px;">
<input type="text" name="myAmt1" placeholder="Amount (dd.cc)"><br>

<input type="file" name="myFile2">
<input type="text" name="myReceipt2" placeholder="Vendor (who was paid)...">
<input type="text" name="myProgram2" placeholder="GenOps, OWP, VSP, etc."><br>
<input type="text" name="myDesc2" placeholder="Expense Desc (e.g. catering, airfare, etc.)" style="width:300px;"><br>
<input type="date" name="myDate2" placeholder="Date Charged (yyyy.mm.dd)" style="width:200px;">
<input type="text" name="myAmt2" placeholder="Amount (dd.cc)"><br>
<input type="submit" value="Upload File(s)" style="background-color:#ffd382" onclick="submitValues(this);return false;">
</form>

<div id = "output"></div>

<script>
function submitValues(e) {
  e.value = 'Uploading...';
  const files = [e.parentNode.myFile1.files[0], e.parentNode.myFile2.files[0]];
  const object = [...e.parentNode].reduce((o, obj) => Object.assign(o, {[obj.name]: obj.value}), {});
  if (files.some(f => f)) {
    Promise.all(
      files.map(file => new Promise((resolve, reject) => {
        if (file) {
          const fr = new FileReader();
          fr.onload = f => resolve({filename: file.name, mimeType: file.type, bytes: [...new Int8Array(f.target.result)]});
          fr.onerror = err => reject(err);
          fr.readAsArrayBuffer(file);
        } else {
          resolve({});
        }
      }))
    ).then(ar => {
      [object.myFile1, object.myFile2] = ar;
      google.script.run.withSuccessHandler(fileUploaded).uploadFiles(object);
    });
  }
}

function fileUploaded(status) {
  document.getElementById('myForm').style.display = 'none';
  document.getElementById('output').innerHTML = status;
}
</script>

Google Apps 脚本端:

在本例中,uploadFiles 已被修改。

function uploadFiles(form) {
  try {
    var dropbox = "Receipts";  //name of Drive folder to save uploaded files
    var folder, folders = DriveApp.getFoldersByName(dropbox);
    if (folders.hasNext()) {
      folder = folders.next();
    } else {
      folder = DriveApp.createFolder(dropbox);
    }
    
    // --- I modified below script.
    var file1 = form.myFile1;
    if (Object.keys(file1).length > 0) {
      var blob = Utilities.newBlob(file1.bytes, file1.mimeType, file1.filename);  // Modified
      var file = folder.createFile(blob);    
      file.setDescription("Uploaded by " + form.myName);
      file.setName(form.myDate1 + "_" + form.myReceipt1 + "_" + form.myProgram1 + "_" + form.myDesc1 + " - " + form.myAmt1);
    }
    var file2 = form.myFile2;
    if (Object.keys(file2).length > 0) {
      var blob = Utilities.newBlob(file2.bytes, file2.mimeType, file2.filename);  // Modified
      var file = folder.createFile(blob);    
      file.setDescription("Uploaded by " + form.myName);
      file.setName(form.myDate2 + "_" + form.myReceipt2 + "_" + form.myProgram2 + "_" + form.myDesc2 + " - " + form.myAmt2);
    }
    // ---
    
    return "Your receipts have been uploaded. Refresh the page if you have more to upload.";
  } catch (error) { 
    return error.toString();
  }
}

注意:

  • 在本例中,最大文件大小小于 50 MB,因为 Google Apps 脚本使用了 Blob。请小心这一点。
  • 在我的环境中,我可以确认提议的脚本有效。但是,如果该脚本在您的环境中不起作用,您能否提供用于复制问题的脚本?借此,我想确认一下。

引用文献:

关于google-apps-script - Google Apps 脚本正在损坏/删除通过我创建的表单上传的所有文件。我该如何解决?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/63714501/

相关文章:

javascript - Google Cloud Print 短肖像页面上的媒体缩放问题

C# ReadAsByteArrayAsync 结果与原始数据不同并导致文件损坏

java - 集群和负载均衡的区别?

java - Struts 2 中的多表单执行

google-apps-script - 如何从 HTML 文件调用 google 脚本函数?

api - 使用 Google Apps 脚本编辑 PDF

python - 使用 Python 使用 Google API 将电子表格复制到另一个

Html 表格 : bad mime type for . zip 文件

mysql - PHP/MySQL : Cannot submit a 2, 5MB-文件到数据库

apache - 每个 Tomcat 的 Axis2 版本