【问题标题】:HTML5 form validation and file upload in Google Apps Script HTML ServiceGoogle Apps Script HTML Service 中的 HTML5 表单验证和文件上传
【发布时间】:2014-12-16 08:58:44
【问题描述】:

我正在使用 HTML 服务开发 GAS,但现在遇到了障碍。我想做的是

  1. 创建一个可以将表单元素(即姓名和电子邮件)中的数据添加到 Google 表格的来源
  2. 该表单还将文件上传到特定的谷歌驱动器
  3. 在 1 和 2 之前,表单应该基于 HTML5 验证输入

这是我的(几乎)工作代码:

代码.gs

function doGet(e) {
    return HtmlService.createHtmlOutputFromFile('index.html');
}

function uploadFiles(form) {
    try {
    var ssID = '-------ssID-------';
    var dropboxID = '-------DriveID-------';
    var folder = DocsList.getFolderById(dropboxID);

    var blob = form.myFile;    

    if ( Boolean(blob) ) {
        var file = folder.createFile(blob);
        file.setDescription("Uploaded by " + form.myName);
    }

var sheet = SpreadsheetApp.openById(ssID).getSheets()[0];
var lastRow = sheet.getLastRow();
var targetRange = sheet.getRange(lastRow+1, 1, 1, 3).setValues([[ form.myName, form.myMail, file.getUrl() ]]);
return "File uploaded successfully"+ file.getUrl() + file.getName();

    } catch (error) {
        return error.name + ' on line: ' + error.lineNumber + ' -> ' + error.message;
    }
}

index.html

<script src="//ajax.googleapis.com/ajax/libs/jquery/1.9.1/jquery.min.js"></script>
<!-- You can also include your own CSS styles -->
<style>
    form { margin: 40px auto; }
    input { display:block; margin: 20px; }
</style>

<!-- This is the actual HTML form -->
<!--form id="myForm" onsubmit="runGAS(this)"-->
<form id="myForm" onsubmit="return google.script.run
    .withSuccessHandler(fileUploaded)
    .uploadFiles(this.parentNode);">

    <!-- Text input fields -->
    <input type="text" name="myName" id="myName" placeholder="Your name.." required />
    <input type="email" name="myMail" id="myMail" placeholder="Your mail.." required />
    <!-- File input filed -->
    <input type="file" name="myFile" id="myFile" required />
    <!-- The submit button. It calls the server side function uploadfiles() on click -->
    <input type="submit" value="run onClick" 
           onclick="this.value='Uploading..';
                    google.script.run.withSuccessHandler(fileUploaded)
                    .uploadFiles(this.parentNode);
                    return false;">
    <input type="submit" value="Run GAS Function">
</form>
<script>

function runGAS( argThis ) {
    var n = $( "#myName" ).val();
    var f = document.getElementById("myFile");
    // var g = $( "myFile" ).val();
    if( Boolean(n) ) {
        document.getElementById('output').innerHTML = "OK" + n + "js: " + f;
        google.script.run.withSuccessHandler(fileUploaded)
        .uploadFiles( argThis );
        document.getElementById('output').innerHTML = e.name + 'on line:' + e.lineNumber + '->' + e.message;
    }
    return false;
}

</script>

<!-- Here the results of the form submission will be displayed -->
<div id="output"></div>

<!-- The function will be called after the Google Script has executed -->
<script>
    function fileUploaded(status) {
        document.getElementById('myForm').style.display = 'none';
        document.getElementById('output').innerHTML = status;
    }
</script>

我遇到了很多建议:

  1. 许多不处理文件上传(仅工作表)的教程会说直接从提交按钮调用,这会绕过 HTML5 验证。这是我的第一个提交按钮名称“run onClick”的示例。
  2. 经过搜索,发现要触发HTML5验证(这里是链接HTML5 form validation with Html Service),另一个标题为“run onClick”的提交按钮的情况,我们应该将GAS函数调用移动到form元素,这样做有助于触发HTML5 验证,但是奇怪的事情发生在 GAS 上,因为它不会,并且 URL 生成典型的带有表单值的 GET(例如,https://script.google.com/a/macros/----/s/---------/dev?myName=va&amp;myMail=vas%40au.edu&amp;myFile=imgName.jpg
  3. 另一种解决方案,有人建议我们可以使用 jQuery 捕获表单提交,以仅在满足所有要求(验证)时触发 GAS 函数调用。这给了我与 2. 相同的结果。 GAS 运行,但返回此页面时未传递任何实际值。

任何解决方案将不胜感激。

2014 年 12 月 19 日编辑

<script>
window.runGAS = function() {
  // jQuery Style
  window.form = $( "#myForm" );
  // OR JS 
  window.form = document.getElementById('myForm');

  google.script.run
  .withSuccessHandler(fileUploaded)
  .uploadFiles(form);
  return false;
}
</script>

我尝试了 Sandy 的建议,在表单元素中省略了函数调用 onsubmit 中的传递值。这有助于触发 HTML5 验证。我想我必须想办法将表单对象(不是单个表单值)传递给code.gs,所以我通过 GAS 函数运行传递表单对象。

如果我使用 jQuery 样式,JavaScript 控制台会报告 Untaming of guest constructed objects unsupported: [object Object]

如果我使用 getElementById,我会遇到同样的问题,它会生成带有 name=value 对的 GET 样式 URL,然后返回 index.html 而没有“执行”code.gs 函数。请注意,它“似乎”以某种方式通过code.gs(即,如果我放置了一些语法错误,它将在此过程中报告),但它并没有像onclick 那样做它应该做的事情。

到目前为止,唯一可行的方法是使用onclick,而不是onsubmit,而不是从标签调用中间GAS。但它绕过了 HTML5 验证。

我真的不知道这里...

【问题讨论】:

    标签: jquery html validation google-apps-script


    【解决方案1】:

    以下是我使用 HTML 服务配置 FORM 的方法:

    <form id="myInputForm" name="input" onsubmit="writeInput()">
    

    我没有在表单中运行onsubmit="return google.script.run。我想我遇到了与您相同或相似的问题。因此,当提交表单时,表单会运行一个 JavaScript 函数 writeInput()。然后 SCRIPT 标记中的 JavaScript 函数运行 google.script.run。这对我有用。当我这样设置时,具有 required 设置的输入字段将阻止提交表单。

    <script>
      window.writeInput = function() {
        window.myInputValue = document.getElementById('idMyInputID').value; //Get input value
        google.script.run
      }
    <script>
    

    您应该对前端和后端进行数据验证。黑客或许能够找到某种方法将他们自己的数据发送到服务器端代码.gs。如果我要在前端、客户端或后端、服务器端选择 任一 验证,我会选择服务器端验证。如果用户的数据输入错误,就快速将消息返回给用户,客户端检查更好,但并不更安全。

    您实际上是在问一个与个人偏好或意见有关的问题。我只是在 HTML 中使用 JavaScript 从输入字段中获取值。

    window.variableName = document.getElementById('id_Name').value;
    

    那行代码将值从表单输入字段中取出,并放入变量中。然后您可以将变量发送到.gs 文件。

    google.script.run.withFailureHandler(onFailure)
          .withSuccessHandler(savedLst)
          .writeInputData(variableName);
    

    以上代码在 HTML 中。函数writeInputData 位于.gs 脚本文件中。

    您可以在调用writeInputData 函数之前检查变量variableName 进行验证。

    if (variableName === "") {
      alert("Missing Input");
      return false;
    } else {
      google.script.run.withFailureHandler(onFailure)
        .withSuccessHandler(savedLst)
        .writeInputData(variableName);
    };
    

    还有其他方法可以进行前端数据验证。您可以组合方法。如果您发现无法修复的错误,请发布错误消息以及它来自哪一行。

    要从 HTML 打印信息,请使用:console.log("some text here: " + variableName); 这将在浏览器的控制台上打印一些内容。打开开发人员工具和控制台以查看已打印到浏览器控制台的内容。不要与Logger.log() 混淆,后者会向服务器端应用程序脚本日志打印一些内容。

    【讨论】:

    • 谢谢桑迪。但是,我仍然遇到上述相同的问题,即,如果我直接从提交按钮调用“onclick”,它会触发 GAS,但会绕过 HTML5。如果我在表单元素上调用 GAS“onsubmit”,它会触发 HTML5 和 GAS,但它会 (1) 生成带有 name=value& 对的 GET 样式 URL ...(2) 它似乎通过 code.gs页面(即,如果我删除函数参数,它会发出警告),但它会返回主页而不处理任何内容。顺便说一句,JSconsole 中没有错误,只是警告“不推荐使用 Attr.ownerElement ...”,这不会影响按钮的 GAS 调用。
    • 嗯...我认为&lt;form id="myForm" name="myForm" onsubmit="google.script.run.uploadFiles(this); "&gt; 不起作用但&lt;form id="myForm" name="myForm" onclick="google.script.run.uploadFiles(this); "&gt; 起作用(但不实用。任何提示为什么会这样?
    • 我已经尝试了您的建议,更新了我遇到的问题(如果我尝试通过google.script.run 传递表单对象也会出现同样的问题...
    • 你知道Logger.log()语句吗?您可以使用 Logger.log("Some text here: " + myVariableName); 将信息打印到 Apps Script LOG 您可以使用它来查看您的 form 变量中包含的内容。如果它是一个对象,它应该显示类似[object][Object] 的内容。将一些Logger.log() 语句放入您的代码中,然后查看日志。如果您将一个对象传递给.gs 代码,那么您可以遍历该对象,并查看它的结构以及其中的内容。被传递的对象可能不是你想象的那样。
    • 再次感谢 Sandy 的调试策略。我确实尝试过Logger.log("sometext"+ var); 这是我发现的。当我通过onsubmit 使用中介&lt;script&gt; 并传递任何参数时,code.gs 不抓取任何东西,服务器端日志中没有报告。当我删除参数时,它工作正常。也就是说,它在Logger.log() 中捕获了那个报告变量,它也可以像我们预期的那样返回值。 onclick 中不会出现此异常。你以前有没有经历过,还是我错过了什么?
    猜你喜欢
    • 1970-01-01
    • 2020-04-11
    • 1970-01-01
    • 2014-07-08
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多