使用 Google Apps 脚本批量导入条目
Multiple bulk import entries using Google Apps Script
我知道现有代码可以构建一个可以上传多个文件(批量导入)的表单,例如 ,但我只是想知道是否可以做一个要求批量导入的表单(或大文件)多次?现有脚本似乎使用 document.getFileByID() 在上传函数中传递一个输入的 ID,我无法在其中传递多个 ID。
这是我所指的代码(从 复制):
function doGet() {
return HtmlService.createHtmlOutputFromFile('form')
.setSandboxMode(HtmlService.SandboxMode.IFRAME);
}
function uploadFileToDrive(base64Data, fileName) {
try{
var splitBase = base64Data.split(','),
type = splitBase[0].split(';')[0].replace('data:','');
var byteCharacters = Utilities.base64Decode(splitBase[1]);
var ss = Utilities.newBlob(byteCharacters, type);
ss.setName(fileName);
var dropbox = "Something"; // Folder Name
var folder, folders = DriveApp.getFoldersByName(dropbox);
if (folders.hasNext()) {
folder = folders.next();
} else {
folder = DriveApp.createFolder(dropbox);
}
var file = folder.createFile(ss);
return file.getName();
}catch(e){
return 'Error: ' + e.toString();
}
}
<body>
<div id="formcontainer">
<label for="myForm">Facilities Project Database Attachment Uploader:</label>
<br><br>
<form id="myForm">
<label for="myForm">Project Details:</label>
<div>
<input type="text" name="zone" placeholder="Zone:">
</div>
<div>
<input type="text" name="building" placeholder="Building(s):">
</div>
<div>
<input type="text" name="propertyAddress" placeholder="Property Address:">
</div>
<div>
<label for="fileText">Project Description:</label>
<TEXTAREA name="projectDescription"
placeholder="Describe your attachment(s) here:"
style ="width:400px; height:200px;"
></TEXTAREA>
</div>
<br>
<label for="attachType">Choose Attachment Type:</label>
<br>
<select name="attachType">
<option value="Pictures Only">Picture(s)</option>
<option value="Proposals Only">Proposal(s)</option>
<option value="Pictures & Proposals">All</option>
</select>
<br>
<label for="myFile">Upload Attachment(s):</label>
<br>
<input type="file" name="filename" id="myFile" multiple>
<input type="button" value="Submit" onclick="iteratorFileUpload()">
</form>
</div>
<div id="output"></div>
<div id="progressbar">
<div class="progress-label"></div>
</div>
<script src="//ajax.googleapis.com/ajax/libs/jquery/1.11.2/jquery.min.js"></script>
<link rel="stylesheet" href="https://ajax.googleapis.com/ajax/libs/jqueryui/1.11.4/themes/smoothness/jquery-ui.css">
<script src="https://ajax.googleapis.com/ajax/libs/jqueryui/1.11.4/jquery-ui.min.js"></script>
<script>
var numUploads = {};
numUploads.done = 0;
numUploads.total = 0;
// Upload the files into a folder in drive
// This is set to send them all to one folder (specificed in the .gs file)
function iteratorFileUpload() {
var allFiles = document.getElementById('myFile').files;
if (allFiles.length == 0) {
alert('No file selected!');
} else {
//Show Progress Bar
numUploads.total = allFiles.length;
$('#progressbar').progressbar({
value : false
});//.append("<div class='caption'>37%</div>");
$(".progress-label").html('Preparing files for upload');
// Send each file at a time
for (var i = 0; i < allFiles.length; i++) {
console.log(i);
sendFileToDrive(allFiles[i]);
}
}
}
function sendFileToDrive(file) {
var reader = new FileReader();
reader.onload = function (e) {
var content = reader.result;
console.log('Sending ' + file.name);
var currFolder = 'Something';
google.script.run.withSuccessHandler(updateProgressbar).uploadFileToDrive(content, file.name, currFolder);
}
reader.readAsDataURL(file);
}
function updateProgressbar( idUpdate ){
console.log('Received: ' + idUpdate);
numUploads.done++;
var porc = Math.ceil((numUploads.done / numUploads.total)*100);
$("#progressbar").progressbar({value: porc });
$(".progress-label").text(numUploads.done +'/'+ numUploads.total);
if( numUploads.done == numUploads.total ){
//uploadsFinished();
numUploads.done = 0;
};
}
</script>
<script>
function fileUploaded(status) {
document.getElementById('myForm').style.display = 'none';
document.getElementById('output').innerHTML = status;
}
</script>
<style>
body {
max-width: 400px;
padding: 20px;
margin: auto;
}
input {
display: inline-block;
width: 100%;
padding: 5px 0px 5px 5px;
margin-bottom: 10px;
-webkit-box-sizing: border-box;
-moz-box-sizing: border-box;
box-sizing: border-box;
}
select {
margin: 5px 0px 15px 0px;
}
input[type="submit"] {
width: auto !important;
display: block !important;
}
input[type="file"] {
padding: 5px 0px 15px 0px !important;
}
#progressbar{
width: 100%;
text-align: center;
overflow: hidden;
position: relative;
vertical-align: middle;
}
.progress-label {
float: left;
margin-top: 5px;
font-weight: bold;
text-shadow: 1px 1px 0 #fff;
width: 100%;
height: 100%;
position: absolute;
vertical-align: middle;
}
</style>
</body>
感谢任何建议!
我相信你的目标如下。
- 您只想使用 2 个输入标签将 2 个文件上传到 Google 驱动器。每个文件大小超过 50 MB。
- 您想使用 Web 应用程序实现此目的。 HTML 放在 Google Apps Script 项目中,包括 Web Apps 的脚本。
问题和解决方法:
在当前阶段,当文件大小超过 50 MB 时,由于 Google 的当前规范,无法使用 Google Apps 脚本将文件内容直接保存为文件边。因此,在这种情况下,需要使用 Drive API 的可恢复上传来上传文件。 Ref 这种情况需要编写实现断点续传的脚本。但是,幸运的是,我已经创建了使用 Javascript 库来实现这一点。在这个答案中,我想提出一个使用这个 Javascript 库的示例脚本。
用法:
1。为 Web 应用程序创建 Google Apps 脚本。
为了使用 Web Apps,请创建一个新的 Google Apps 脚本项目。
2。示例脚本。
请将以下脚本复制并粘贴到已创建的 Google Apps 脚本项目的脚本编辑器中。
Google Apps 脚本端:Code.gs
function main() {
var html = HtmlService.createHtmlOutputFromFile("index");
SpreadsheetApp.getUi().showSidebar(html);
}
function getAuth() {
// DriveApp.createFile() // This is used for adding the scope of "https://www.googleapis.com/auth/drive".
return ScriptApp.getOAuthToken();
}
HTML & Javascript 边: index.html
<input type="file" id="file1" />
<input type="file" id="file2" />
<input type="button" onclick="run()" value="Upload" />
<div id="progress"></div>
<script src="https://cdn.jsdelivr.net/gh/tanaikech/ResumableUploadForGoogleDrive_js@master/resumableupload_js.min.js"></script>
<script>
function run() {
google.script.run.withSuccessHandler(accessToken => ResumableUploadForGoogleDrive(accessToken)).getAuth();
}
function ResumableUploadForGoogleDrive(accessToken) {
const f1 = document.getElementById("file1").files[0];
const f2 = document.getElementById("file2").files[0];
[f1, f2].forEach((file, i) => {
if (!file) return;
let fr = new FileReader();
fr.fileName = file.name;
fr.fileSize = file.size;
fr.fileType = file.type;
fr.readAsArrayBuffer(file);
fr.onload = e => {
var id = "p" + ++i;
var div = document.createElement("div");
div.id = id;
document.getElementById("progress").appendChild(div);
document.getElementById(id).innerHTML = "Initializing.";
const f = e.target;
const resource = { fileName: f.fileName, fileSize: f.fileSize, fileType: f.fileType, fileBuffer: f.result, accessToken: accessToken };
const ru = new ResumableUploadToGoogleDrive();
ru.Do(resource, function (res, err) {
if (err) {
console.log(err);
return;
}
console.log(res);
let msg = "";
if (res.status == "Uploading") {
msg = Math.round((res.progressNumber.current / res.progressNumber.end) * 100) + "% (" + f.fileName + ")";
} else {
msg = res.status + " (" + f.fileName + ")";
}
// if (res.status == "Done") google.script.run.putFileInf(res.result);
document.getElementById(id).innerText = msg;
});
};
});
}
</script>
当您要将上传的文件放到指定文件夹时,请修改const resource = { fileName: f.fileName, fileSize: f.fileSize, fileType: f.fileType, fileBuffer: f.result, accessToken: accessToken };
如下。
const resource = { fileName: f.fileName, fileSize: f.fileSize, fileType: f.fileType, fileBuffer: f.result, accessToken: accessToken, folderId: "###folderId###" };
3。启用驱动器 API.
Please enable Drive API at Advanced Google services.
4。部署 Web 应用程序。
详细信息见the official document。
- 在脚本编辑器上,在脚本编辑器的右上角,请点击“单击部署”->“新建部署”。
- 请点击“Select类型”->“Web App”。
- 请在“部署配置”下的字段中输入有关 Web 应用程序的信息。
- 请select“我”为“执行为”。
- 这就是此解决方法的重要性。
- 请 select “任何人” “谁有权访问”。
- 为了测试这个脚本,我认为这个设置可能是合适的。
- 请点击“部署”按钮。
- 复制 Web App 的 URL。就像
https://script.google.com/macros/s/###/exec
。
- 当您修改 Google Apps 脚本时,请将部署修改为新版本。这样,修改后的脚本就会反映在 Web Apps 中。请注意这一点。
- 您可以在“Redeploying Web Apps without Changing URL of Web Apps for new IDE”的报告中看到详细信息。
5。测试:
作为一个简单的示例脚本,当上面的HTML和Javascript在侧边栏上运行时,得到如下结果。当然,这个结果可以使用Web Apps获得。测试这个脚本,可以看到文件是可以异步上传的。本演示来自here.
注:
在这种情况下,使用 ScriptApp.getOAuthToken()
从 Google Apps 脚本端检索访问令牌。为了测试此脚本,您可以使用 https://www.googleapis.com/auth/drive
的范围。但是,如果你想在实际情况下使用这个脚本时保持安全,我建议使用 https://www.googleapis.com/auth/drive.file
作为范围。这样,访问令牌只能访问此客户端创建的文件。
当您修改 Google Apps 脚本时,请将部署修改为新版本。这样,修改后的脚本就会反映在 Web Apps 中。请注意这一点。
你可以在“Redeploying Web Apps without Changing URL of Web Apps for new IDE”的报告中看到详细信息。
参考文献:
我知道现有代码可以构建一个可以上传多个文件(批量导入)的表单,例如
这是我所指的代码(从
function doGet() {
return HtmlService.createHtmlOutputFromFile('form')
.setSandboxMode(HtmlService.SandboxMode.IFRAME);
}
function uploadFileToDrive(base64Data, fileName) {
try{
var splitBase = base64Data.split(','),
type = splitBase[0].split(';')[0].replace('data:','');
var byteCharacters = Utilities.base64Decode(splitBase[1]);
var ss = Utilities.newBlob(byteCharacters, type);
ss.setName(fileName);
var dropbox = "Something"; // Folder Name
var folder, folders = DriveApp.getFoldersByName(dropbox);
if (folders.hasNext()) {
folder = folders.next();
} else {
folder = DriveApp.createFolder(dropbox);
}
var file = folder.createFile(ss);
return file.getName();
}catch(e){
return 'Error: ' + e.toString();
}
}
<body>
<div id="formcontainer">
<label for="myForm">Facilities Project Database Attachment Uploader:</label>
<br><br>
<form id="myForm">
<label for="myForm">Project Details:</label>
<div>
<input type="text" name="zone" placeholder="Zone:">
</div>
<div>
<input type="text" name="building" placeholder="Building(s):">
</div>
<div>
<input type="text" name="propertyAddress" placeholder="Property Address:">
</div>
<div>
<label for="fileText">Project Description:</label>
<TEXTAREA name="projectDescription"
placeholder="Describe your attachment(s) here:"
style ="width:400px; height:200px;"
></TEXTAREA>
</div>
<br>
<label for="attachType">Choose Attachment Type:</label>
<br>
<select name="attachType">
<option value="Pictures Only">Picture(s)</option>
<option value="Proposals Only">Proposal(s)</option>
<option value="Pictures & Proposals">All</option>
</select>
<br>
<label for="myFile">Upload Attachment(s):</label>
<br>
<input type="file" name="filename" id="myFile" multiple>
<input type="button" value="Submit" onclick="iteratorFileUpload()">
</form>
</div>
<div id="output"></div>
<div id="progressbar">
<div class="progress-label"></div>
</div>
<script src="//ajax.googleapis.com/ajax/libs/jquery/1.11.2/jquery.min.js"></script>
<link rel="stylesheet" href="https://ajax.googleapis.com/ajax/libs/jqueryui/1.11.4/themes/smoothness/jquery-ui.css">
<script src="https://ajax.googleapis.com/ajax/libs/jqueryui/1.11.4/jquery-ui.min.js"></script>
<script>
var numUploads = {};
numUploads.done = 0;
numUploads.total = 0;
// Upload the files into a folder in drive
// This is set to send them all to one folder (specificed in the .gs file)
function iteratorFileUpload() {
var allFiles = document.getElementById('myFile').files;
if (allFiles.length == 0) {
alert('No file selected!');
} else {
//Show Progress Bar
numUploads.total = allFiles.length;
$('#progressbar').progressbar({
value : false
});//.append("<div class='caption'>37%</div>");
$(".progress-label").html('Preparing files for upload');
// Send each file at a time
for (var i = 0; i < allFiles.length; i++) {
console.log(i);
sendFileToDrive(allFiles[i]);
}
}
}
function sendFileToDrive(file) {
var reader = new FileReader();
reader.onload = function (e) {
var content = reader.result;
console.log('Sending ' + file.name);
var currFolder = 'Something';
google.script.run.withSuccessHandler(updateProgressbar).uploadFileToDrive(content, file.name, currFolder);
}
reader.readAsDataURL(file);
}
function updateProgressbar( idUpdate ){
console.log('Received: ' + idUpdate);
numUploads.done++;
var porc = Math.ceil((numUploads.done / numUploads.total)*100);
$("#progressbar").progressbar({value: porc });
$(".progress-label").text(numUploads.done +'/'+ numUploads.total);
if( numUploads.done == numUploads.total ){
//uploadsFinished();
numUploads.done = 0;
};
}
</script>
<script>
function fileUploaded(status) {
document.getElementById('myForm').style.display = 'none';
document.getElementById('output').innerHTML = status;
}
</script>
<style>
body {
max-width: 400px;
padding: 20px;
margin: auto;
}
input {
display: inline-block;
width: 100%;
padding: 5px 0px 5px 5px;
margin-bottom: 10px;
-webkit-box-sizing: border-box;
-moz-box-sizing: border-box;
box-sizing: border-box;
}
select {
margin: 5px 0px 15px 0px;
}
input[type="submit"] {
width: auto !important;
display: block !important;
}
input[type="file"] {
padding: 5px 0px 15px 0px !important;
}
#progressbar{
width: 100%;
text-align: center;
overflow: hidden;
position: relative;
vertical-align: middle;
}
.progress-label {
float: left;
margin-top: 5px;
font-weight: bold;
text-shadow: 1px 1px 0 #fff;
width: 100%;
height: 100%;
position: absolute;
vertical-align: middle;
}
</style>
</body>
感谢任何建议!
我相信你的目标如下。
- 您只想使用 2 个输入标签将 2 个文件上传到 Google 驱动器。每个文件大小超过 50 MB。
- 您想使用 Web 应用程序实现此目的。 HTML 放在 Google Apps Script 项目中,包括 Web Apps 的脚本。
问题和解决方法:
在当前阶段,当文件大小超过 50 MB 时,由于 Google 的当前规范,无法使用 Google Apps 脚本将文件内容直接保存为文件边。因此,在这种情况下,需要使用 Drive API 的可恢复上传来上传文件。 Ref 这种情况需要编写实现断点续传的脚本。但是,幸运的是,我已经创建了使用 Javascript 库来实现这一点。在这个答案中,我想提出一个使用这个 Javascript 库的示例脚本。
用法:
1。为 Web 应用程序创建 Google Apps 脚本。
为了使用 Web Apps,请创建一个新的 Google Apps 脚本项目。
2。示例脚本。
请将以下脚本复制并粘贴到已创建的 Google Apps 脚本项目的脚本编辑器中。
Google Apps 脚本端:Code.gs
function main() {
var html = HtmlService.createHtmlOutputFromFile("index");
SpreadsheetApp.getUi().showSidebar(html);
}
function getAuth() {
// DriveApp.createFile() // This is used for adding the scope of "https://www.googleapis.com/auth/drive".
return ScriptApp.getOAuthToken();
}
HTML & Javascript 边: index.html
<input type="file" id="file1" />
<input type="file" id="file2" />
<input type="button" onclick="run()" value="Upload" />
<div id="progress"></div>
<script src="https://cdn.jsdelivr.net/gh/tanaikech/ResumableUploadForGoogleDrive_js@master/resumableupload_js.min.js"></script>
<script>
function run() {
google.script.run.withSuccessHandler(accessToken => ResumableUploadForGoogleDrive(accessToken)).getAuth();
}
function ResumableUploadForGoogleDrive(accessToken) {
const f1 = document.getElementById("file1").files[0];
const f2 = document.getElementById("file2").files[0];
[f1, f2].forEach((file, i) => {
if (!file) return;
let fr = new FileReader();
fr.fileName = file.name;
fr.fileSize = file.size;
fr.fileType = file.type;
fr.readAsArrayBuffer(file);
fr.onload = e => {
var id = "p" + ++i;
var div = document.createElement("div");
div.id = id;
document.getElementById("progress").appendChild(div);
document.getElementById(id).innerHTML = "Initializing.";
const f = e.target;
const resource = { fileName: f.fileName, fileSize: f.fileSize, fileType: f.fileType, fileBuffer: f.result, accessToken: accessToken };
const ru = new ResumableUploadToGoogleDrive();
ru.Do(resource, function (res, err) {
if (err) {
console.log(err);
return;
}
console.log(res);
let msg = "";
if (res.status == "Uploading") {
msg = Math.round((res.progressNumber.current / res.progressNumber.end) * 100) + "% (" + f.fileName + ")";
} else {
msg = res.status + " (" + f.fileName + ")";
}
// if (res.status == "Done") google.script.run.putFileInf(res.result);
document.getElementById(id).innerText = msg;
});
};
});
}
</script>
当您要将上传的文件放到指定文件夹时,请修改
const resource = { fileName: f.fileName, fileSize: f.fileSize, fileType: f.fileType, fileBuffer: f.result, accessToken: accessToken };
如下。const resource = { fileName: f.fileName, fileSize: f.fileSize, fileType: f.fileType, fileBuffer: f.result, accessToken: accessToken, folderId: "###folderId###" };
3。启用驱动器 API.
Please enable Drive API at Advanced Google services.
4。部署 Web 应用程序。
详细信息见the official document。
- 在脚本编辑器上,在脚本编辑器的右上角,请点击“单击部署”->“新建部署”。
- 请点击“Select类型”->“Web App”。
- 请在“部署配置”下的字段中输入有关 Web 应用程序的信息。
- 请select“我”为“执行为”。
- 这就是此解决方法的重要性。
- 请 select “任何人” “谁有权访问”。
- 为了测试这个脚本,我认为这个设置可能是合适的。
- 请点击“部署”按钮。
- 复制 Web App 的 URL。就像
https://script.google.com/macros/s/###/exec
。- 当您修改 Google Apps 脚本时,请将部署修改为新版本。这样,修改后的脚本就会反映在 Web Apps 中。请注意这一点。
- 您可以在“Redeploying Web Apps without Changing URL of Web Apps for new IDE”的报告中看到详细信息。
5。测试:
作为一个简单的示例脚本,当上面的HTML和Javascript在侧边栏上运行时,得到如下结果。当然,这个结果可以使用Web Apps获得。测试这个脚本,可以看到文件是可以异步上传的。本演示来自here.
注:
在这种情况下,使用
ScriptApp.getOAuthToken()
从 Google Apps 脚本端检索访问令牌。为了测试此脚本,您可以使用https://www.googleapis.com/auth/drive
的范围。但是,如果你想在实际情况下使用这个脚本时保持安全,我建议使用https://www.googleapis.com/auth/drive.file
作为范围。这样,访问令牌只能访问此客户端创建的文件。当您修改 Google Apps 脚本时,请将部署修改为新版本。这样,修改后的脚本就会反映在 Web Apps 中。请注意这一点。
你可以在“Redeploying Web Apps without Changing URL of Web Apps for new IDE”的报告中看到详细信息。