javascript - Google Apps 脚本文件上传(通过 HTML 表单)仅在脚本为 "bound"时有效(测试独立脚本时,HTTP 403 错误)

标签 javascript forms google-apps-script upload http-status-code-403

要将本地文件上传到 Google 云端硬盘,我有一个 HTML <form></form> (参见下面的代码)以模式显示在用户打开的 Google 表格之上。 HTML 表单有 <input type="file" name="...">当我点击发送表单对象时,我成功上传了文件如果此 Google Apps 脚本“绑定(bind)”到特定的表格文件(并且编写为使用 Tools > Script Editor... 菜单)。

如果我将脚本保存为独立脚本,然后在我选择的表格文件上测试它(已安装并启用),则<form>的 onclick 操作并尝试调用 google.script.run.aServerFunction(...)导致"NetworkError: Connection failure due to HTTP 403" 。为了澄清这一点,我的意思是创建一个独立脚本并在表格文件上测试它:https://developers.google.com/apps-script/add-ons/#understand_the_development_cycle 。在早期的代码迭代中,我或者得到了某种授权脚本错误。当脚本被私下发布以供测试人员在工作表上使用时,会出现同样的错误。不幸的是,我认为我需要它作为一个独立的脚本,稍后可以作为附加组件发布 - 而不是使用 Tools > Script Editor... 绑定(bind)到单个工作表的辅助脚本。菜单。

我在 Stack Overflow 上发表的第一篇文章 - 请原谅任何行话或排版错误,谢谢!

改编自教程的 HTML:

    <!DOCTYPE html>
<html>
  <head>
    <base target="_top">
    <link rel="stylesheet" href="https://ssl.gstatic.com/docs/script/css/add-ons1.css">
    <script src="//ajax.googleapis.com/ajax/libs/jquery/1.9.1/jquery.min.js">
    </script>
    <script>
        function failed(event) {
          $("div.response").text(event);
          //google.script.run.selectStuff();
          //google.script.host.close();
        }
      </script>
  </head>
  <body>
    <form id="myForm">

    <label>Your Name</label>
    <input type="text" name="myName">

    <label>Pick a file</label>
    <input type="file" name="myFile">

    <input type="submit" value="Upload File" 
               onclick="google.script.run.withFailureHandler(failed)
                        .uploadFiles(this.parentNode);
                        return false;">
</form>
<div class="response"></div>
  </body>

</html>

在code.gs中:

function uploadFiles(formObject) {
  /*var sheet1 = SpreadsheetApp.getActiveSheet();
  sheet1.setActiveRange(sheet1.getRange(2, 2, 4, 4));

  var formBlob = formObject.myFile;
  var driveFile = DriveApp.createFile(formBlob);
  driveFile.addEditor("...");
  SpreadsheetApp.getActive().toast(driveFile.getUrl());
  sheet1.getRange(1,1,1,1).setValue(driveFile.getUrl());
  return driveFile.getUrl();*/

  return "it worked";
}

最佳答案

我相信您收到 HTTP 403 错误的原因是因为表单 DOM 元素是工作表插件中的 google.script.run.myfunction(...) 中的非法参数。尽管它们在这里被提及为合法参数 here ,我认为附加组件有一个额外的限制,即无法传递任何类型的 DOM 元素。

我想出的解决方案是使用Filereader.readAsDataUrl()将上传的文件转换为base64编码字符串。函数在 native javascript中并将字符串传递给谷歌脚本并将其转换回要上传到谷歌驱动器的文件。 Base64 编码字符串的开头如下:

data:application/pdf;base64,JVBERi0xLjMKJcTl8uXrp/Og0MTG....

天然气

function uploadFiles(formObject) {
  // extract contentType from the encoded string 
  var contentType = formObject.split(",")[0].split(";")[0].split(":")[1]
  // New Blob(data,contentType,name)
  // Use base64decode to get file data
  var blob = Utilities.newBlob(Utilities.base64Decode(formObject.split(",")[1]), contentType, "trial")
  var driveFile = DriveApp.getFolderById("your Folder ID here").createFile(blob);
  //return contentType, can be anything you like
  return blob.getContentType()
}

HTML 脚本

<!DOCTYPE html>
<html>
  <head>
    <base target="_top">
    <link rel="stylesheet" href="https://ssl.gstatic.com/docs/script/css/add-ons1.css">
    <script src="//ajax.googleapis.com/ajax/libs/jquery/1.9.1/jquery.min.js">
    </script>

  </head>
  <body>
    <form id="myForm">

    <label>Your Name</label>
    <input type="text" name="myName">

    <label>Pick a file</label>
    <input type="file" id = "filemy" name="myFile">

    <input type="button" value="Upload File" 
               onclick="upload(this.parentNode)">
</form>
<div class="response"></div>
  </body>
  <script>
        function failed(event) {
          $("div.response").text(event);
          //google.script.run.selectStuff();
          //google.script.host.close();
        }

        function upload(frmData){
        var file = document.getElementById("filemy").files[0]
        var reader = new FileReader()
        //reader.onload is triggered when readAsDataURL is has finished encoding
        //This will take a bit of time, so be patient
        reader.onload = function(event) {
        // The file's text will be printed here
        console.log("File being Uploaded")
        //console.log(event.target.result)
        google.script.run.withFailureHandler(failed).withSuccessHandler(failed)
                        .uploadFiles(event.target.result);
        };

        reader.readAsDataURL(file);
        console.log(reader.result)
        }
      </script>

</html>

最后的说明:我还没有广泛测试代码,我已经让它可以处理最大大小为 2.6MB 的 pdf 文件和图像/png 文件。因此,请先尝试这两种文件类型,然后再继续使用其他类型的文件! 另外,文件上传确实需要一段时间,所以请耐心等待(~5-10 秒)。尤其是没有进度条显示上传进度,感觉就像什么都没发生一样。

希望有帮助!

关于javascript - Google Apps 脚本文件上传(通过 HTML 表单)仅在脚本为 "bound"时有效(测试独立脚本时,HTTP 403 错误),我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/43170545/

相关文章:

javascript - 针对夜间 Firefox 构建运行 Protractor

javascript - 请求 SQL 2 左外连接

javascript - 从 javascript 设置 html 值?

google-apps-script - Google Apps 脚本页面未打开

javascript - 根据 IF 语句测试范围值数组的最佳方法

php - 登录系统设计允许每个用户一次登录一台机器

Javascript正则表达式删除任何空格、特殊字符和数字

php - 将 Symfony 表单单击按钮映射到数据类

ruby-on-rails - Rails 中的 f.select 不应用 Bootstrap

javascript - 如何将单元格中的数字限制为 x 个小数点?