如何将文件上传Blob从HTML表单传递到服务器端Apps脚本? [英] How to pass file upload blob from HTML form to server-side Apps Script?
问题描述
表单"标题下的Google 支持文章示例已损坏.摘自文章:
The Google support article example under the Forms heading is broken. From the article:
如果以表单元素作为参数调用服务器函数,则表单将成为一个单独的对象,其字段名称为键,字段值作为值.这些值都将转换为字符串,但文件输入字段的内容除外,这些内容成为Blob对象.
If you call a server function with a form element as a parameter, the form becomes a single object with field names as keys and field values as values. The values are all converted to strings, except for the contents of file-input fields, which become Blob objects.
我通过传递一个包含5个文本输入和一个文件的Form元素,然后在表单对象上记录 Object.keys()
来进行测试.它仅返回5个文本字段,文件已从表单对象中剥离.尝试直接直接分配文件blob返回异常:无效参数:blob
I tested this by passing a Form element containing 5 text inputs and a file, then logging Object.keys()
on the form object. It returned only the 5 text fields, the file was stripped from the form object. Attempting to assign the file blob directly returned Exception: Invalid argument: blob
如何将文件格式从客户端表单传递到服务器端Apps脚本?
How do I pass the file blob from the client-side Form to the server-side Apps Script?
编辑:为澄清起见,我还逐字粘贴了Google提供的示例.出现 Exception:无效参数:blob
时出错.
EDIT: To clarify, I also copy-pasted the example provided by Google verbatim. It errors with Exception: Invalid argument: blob
.
要复制:
- 创建新的Google Apps脚本项目
- Index.html内容:
<!DOCTYPE html>
<html>
<head>
<base target="_top">
<script>
// Prevent forms from submitting.
function preventFormSubmit() {
var forms = document.querySelectorAll('form');
for (var i = 0; i < forms.length; i++) {
forms[i].addEventListener('submit', function(event) {
event.preventDefault();
});
}
}
window.addEventListener('load', preventFormSubmit);
function handleFormSubmit(formObject) {
google.script.run.withSuccessHandler(updateUrl).processForm(formObject);
}
function updateUrl(url) {
var div = document.getElementById('output');
div.innerHTML = '<a href="' + url + '">Got it!</a>';
}
</script>
</head>
<body>
<form id="myForm" onsubmit="handleFormSubmit(this)">
<input name="myFile" type="file" />
<input type="submit" value="Submit" />
</form>
<div id="output"></div>
</body>
</html>
- Code.gs内容:
function doGet() {
return HtmlService.createHtmlOutputFromFile('Index');
}
function processForm(formObject) {
var formBlob = formObject.myFile;
var driveFile = DriveApp.createFile(formBlob);
return driveFile.getUrl();
}
- 发布为Web App
- 提交包含任何文件的表格
- 在视图-> Stackdriver Logging-> Apps脚本仪表板中观察错误
推荐答案
我可以确认这在G-Suite Enterprise中不起作用.我不知道为什么,因为我找不到说明Google如何序列化数据的文档.它可能是浏览器/计算机的安全性设置,也可能是G-Suite中的某种设置.
I can confirm that this doesn't work in G-Suite Enterprise. I don't know why because I cannot find documentation that says how Google is serializing the data. It could be a browser/computer security setting or something in G-Suite.
但是,有一种更简单的方法可以满足您的需求.您可以将Google表单与文件上传问题一起使用,然后在其上创建表单提交
触发器/事件,以将文件复制到团队/共享驱动器.如果您要将触发器附加到Google表单本身,请参见以下示例代码:
However, there is an easier way to accomplish your need. You can use a Google Form with a file upload question and then create an on form submit
trigger/event on it to copy the file to a team/shared drive. Here is sample code if you want to attach the trigger to the Google Form itself:
// ID of the destnation folder to save the file in
var destinationFolderID = "10gkU_2V9iYy-VKudOCOjydEpoepPTgPv"
function saveFileToTeamDrive(e)
{
// a place to save the URL of the uploaded file
var fileID;
// go through all of the responses to find the URL of the uploaded file
e.response.getItemResponses().forEach(function(itemResponse){
// once we find the question with the file
if(itemResponse.getItem().getTitle() == "File Upload Test")
{
// get the file ID from the response
fileID = itemResponse.getResponse();
return;
}
});
// stop if we didn't have one
if(!fileID.length) return;
// get the first index in the array
fileID = fileID[0];
// get the file
var file = DriveApp.getFileById(fileID);
// get the destination folder
var destinationFolder = DriveApp.getFolderById(destinationFolderID);
// make a copy
var newFile = file.makeCopy(destinationFolder);
Logger.log(newFile.getUrl());
}
您还可以将链接到Google表单的Google表格的 on表单提交
事件附加到事件.我发现这种方式更容易,因为Google表单在表单上提交
触发器/事件包含问题/答案的JSON,因此您无需遍历所有问题即可找到它.这也意味着如果提交失败,您可以重新运行.
You can also attach to the on form submit
event of a Google Sheet that is linked to a Google Form. I find that way easier cause the Google Sheet on form submit
trigger/event includes a JSON of the question/answers so you don't have to iterate all of them to find it. It also means you can re-run a submission if it failed.
一个重要的注意事项,如果您执行上述任何一项操作,则不会授予其他任何人对该代码的编辑权限.这是因为,一旦您创建并授权了触发器,任何拥有对代码的编辑访问权限的人都将能够使用它来访问您的Google云端硬盘(以及触发器有权使用的其他任何内容).请参阅确保链接到授权触发器的Google Apps脚本,以便其他人可以编辑以获取更多信息.
One important note, if you do either of these things do not give anyone else edit access to the code. This is because as soon as you create and authorize the trigger, anyone who has edit access to the code would be able to use it to gain access to your Google Drive (and anything else the trigger is authorized for). Please see securing a Google Apps Script linked to an authorized trigger so others can edit for more information.
这篇关于如何将文件上传Blob从HTML表单传递到服务器端Apps脚本?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!