Google Apps Script使用continuationToken报Invalid argument错误如何解决
问题根源
- 条件判断逻辑完全写反:你把
continuationToken不为空时才调用continueFileIterator的逻辑写反了,现在的代码是continuationToken == null的时候才会进入外层if,内部else分支刚好在token为空时触发DriveApp.continueFileIterator(null),直接导致报错。
- 条件判断逻辑完全写反:你把
- 变量作用域冲突:全局声明了
continuationToken,又在函数内部用var重复声明同名变量,变量提升导致读取token时拿到的是未赋值的局部变量,始终为null。
- 变量作用域冲突:全局声明了
- 业务逻辑和迭代器逻辑完全混淆:你原本的需求是遍历表格里的指定文件ID删除,和Drive文件迭代器的适用场景不匹配,代码里
start/end/maxTime变量完全没有定义,也没有初始化files迭代器的逻辑,就算修复token问题也无法运行。
- 业务逻辑和迭代器逻辑完全混淆:你原本的需求是遍历表格里的指定文件ID删除,和Drive文件迭代器的适用场景不匹配,代码里
修正方案
如果你是要批量删除表格中当前用户匹配的文件,同时需要处理执行超时的场景,用continuationToken记录表格的遍历进度即可,不需要调用Drive的文件迭代器,修正后代码如下:
const sheetID = "IDgoeshere"; //存储ID和用户名的表格ID const sheetName = 'Sheet1' //表格里的工作表名称 const MAX_RUNTIME = 5 * 60 * 1000; //单轮最大执行时间,这里设5分钟 function deleteFile() { const emailID = Session.getActiveUser().getEmail(); const userProperties = PropertiesService.getUserProperties(); // 读取上一次的进度,默认从第2行开始(跳过表头) let lastProcessedRow = Number(userProperties.getProperty('LAST_PROCESSED_ROW')) || 2; const spreadsheet = SpreadsheetApp.openById(sheetID); const sheet = spreadsheet.getSheetByName(sheetName); const lastRow = sheet.getLastRow(); const values = sheet.getRange(lastProcessedRow, 4, lastRow - lastProcessedRow + 1, 3).getValues(); const startTime = Date.now(); let currentRow = lastProcessedRow; for (let i = 0; i < values.length; i++) { // 接近执行时长上限时保存进度退出 if (Date.now() - startTime >= MAX_RUNTIME) { userProperties.setProperty('LAST_PROCESSED_ROW', String(currentRow)); console.log(`执行超时,已保存进度,下次从第${currentRow}行继续执行`); return; } const row = values[i]; const owner = row[0]; const rowEmail = row[1]; const id = row[2]; if (emailID == rowEmail) { try { const file = DriveApp.getFileById(id); if (file.isTrashed()) { console.info(`文件ID${id}已被删除`); } else { file.setTrashed(true); console.info(`已删除文件ID${id}`); } } catch (e) { console.info(`找不到ID为${id}的文件,错误:${e.message}`); } } currentRow++; } // 全部处理完成,删除进度标记 userProperties.deleteProperty('LAST_PROCESSED_ROW'); console.log('所有文件处理完成'); }
如果你确实需要用到Drive文件迭代器的continuationToken,需要先初始化迭代器再处理,不要和表格遍历的逻辑混写:
const userProperties = PropertiesService.getUserProperties(); const MAX_RUNTIME = 5 * 60 * 1000; function deleteDriveFiles() { let continuationToken = userProperties.getProperty('CONTINUATION_TOKEN'); let files; // 有token就续跑,没有就新建迭代器,这里按自己的需求写搜索条件 if (continuationToken) { files = DriveApp.continueFileIterator(continuationToken); } else { files = DriveApp.getFiles(); //这里可以替换成你需要的搜索条件,比如DriveApp.searchFiles('') } const startTime = Date.now(); while (files.hasNext() && Date.now() - startTime < MAX_RUNTIME) { const file = files.next(); // 这里加你自己的删除判断逻辑 try { file.setTrashed(true); } catch (e) { console.info(`删除文件${file.getName()}失败:${e.message}`); } } if (files.hasNext()) { userProperties.setProperty('CONTINUATION_TOKEN', files.getContinuationToken()); } else { userProperties.deleteProperty('CONTINUATION_TOKEN'); } }
内容的提问来源于stack exchange,提问作者levenoples
相关产品推荐
相关产品推荐

