如何将文件上传 blob 从 HTML 表单传递到服务器端应用脚本?



表单标题下的Google支持文章示例已损坏。 来自文章:

如果使用表单元素作为参数调用服务器函数,则表单将成为单个对象,其中字段名称作为键,字段值作为值。这些值都转换为字符串,但文件输入字段的内容除外,这些字段将成为 Blob 对象。

我通过传递一个包含 5 个文本输入和一个文件的 Form 元素,然后在表单对象上记录Object.keys()来测试这一点。 它只返回了 5 个文本字段,该文件已从表单对象中删除。 尝试分配文件 Blob 直接返回Exception: Invalid argument: blob

如何将文件 blob 从客户端窗体传递到服务器端应用脚本?

编辑:为了澄清,我还逐字复制粘贴了Google提供的示例。它错误与Exception: Invalid argument: blob.

要重现:

  1. 创建新的 Google Apps 脚本项目
  2. 索引.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>
  1. Code.gs 内容:
function doGet() {
return HtmlService.createHtmlOutputFromFile('Index');
}
function processForm(formObject) {
var formBlob = formObject.myFile;
var driveFile = DriveApp.createFile(formBlob);
return driveFile.getUrl();
}
  1. 发布为 Web 应用
  2. 提交包含任何文件的表单
  3. 在视图 -> 堆栈驱动程序日志记录 -> 应用程序脚本仪表板中观察错误

下面是一个示例:

.html:

<!DOCTYPE html>
<html>
<head>
<link rel="stylesheet" href="//code.jquery.com/ui/1.12.1/themes/base/jquery-ui.css">
<script src="https://ajax.googleapis.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<script src="https://code.jquery.com/ui/1.12.1/jquery-ui.js"></script>
<script>
function fileUploadJs(frmData) {
document.getElementById('status').style.display ='inline';
google.script.run
.withSuccessHandler(updateOutput)
.uploadTheFile(frmData)
}
function updateOutput(info)  {
var br='<br />';
var outputDiv = document.getElementById('status');
outputDiv.innerHTML = br + 'File Upload Successful.' + br + 'File Name: ' + info.name + br + 'Content Type: ' + info.type + br + 'Folder Name: ' + info.folder;
}
console.log('My Code');
</script>
<style>
body {background-color:#ffffff;}
input{padding:2px;margin:2px;}
</style>
</head>
<body>
<h1 id="main-heading">Walking Tracks</h1>
<h3>Upload GPS Tracks Files</h3>
<div id="formDiv">
<form id="myForm">
<input name="fileToLoad" type="file" /><br/>
<input type="button" value="Submit" onclick="fileUploadJs(this.parentNode)" />
</form>
</div>
<div id="status" style="display: none">
<!-- div will be filled with innerHTML after form submission. -->
Uploading. Please wait...
</div>  
<div id="controls">
<input type="button" value="Close" onClick="google.script.host.close();" />
</div>
</body>
</html>

服务器代码:

function uploadTheFile(theForm) {
var fileBlob=theForm.fileToLoad;
var fldr = DriveApp.getFolderById('FolderId');
var file=fldr.createFile(fileBlob);
var fi=formatFileName(file);
var fileInfo={'name':fi.getName(),'type':fileBlob.getContentType(), 'size':fileBlob.getBytes(), 'folder':fldr.getName()};
return fileInfo;
}

我可以确认这在G-Suite Enterprise中不起作用。我不知道为什么,因为我找不到说明Google如何序列化数据的文档。它可能是浏览器/计算机安全设置或 G-Suite 中的某些内容。

但是,有一种更简单的方法可以满足您的需求。您可以将 Google 表单与文件上传问题一起使用,然后在表单上创建on form submit触发器/事件,以将文件复制到团队/共享云端硬盘。如果您想将触发器附加到 Google 表单本身,以下是示例代码:

// 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 form submit事件。我发现这种方式更容易,因为 Google 表格on form submit触发器/事件包含问题/答案的 JSON,因此您不必迭代所有问题/答案即可找到它。这也意味着,如果提交失败,您可以重新运行提交。

警告

一个重要的注意事项是,如果您执行上述任一操作,请不要授予其他任何人对代码的编辑访问权限。这是因为,只要您创建并授权触发器,任何拥有代码编辑权限的人都可以使用它来访问您的 Google 云端硬盘(以及触发器授权的任何其他内容(。有关详细信息,请参阅保护链接到授权触发器的 Google Apps 脚本,以便其他人可以进行编辑。

相关内容

最新更新