如何将 ContinuationToken 与递归文件夹迭代器一起使用

2023-11-27

由于 Drive API 配额,服务配额以及脚本执行时间的限制6 min将 Google Drive 文件操作拆分为多个块通常很重要。

我们可以用属性服务储藏continuationToken for 文件夹迭代器 or 文件迭代器。 这样我们就可以停止我们的脚本,并在下次运行时从我们停止的地方继续。

工作示例(线性迭代器)

  // Logs the name of every file in the User's Drive
  // this is useful as the script may take more that 5 minutes (max execution time)
  var userProperties = PropertiesService.getUserProperties();
  var continuationToken = userProperties.getProperty('CONTINUATION_TOKEN');
  var start = new Date();
  var end = new Date();
  var maxTime = 1000*60*4.5; // Max safe time, 4.5 mins

  if (continuationToken == null) {
    // firt time execution, get all files from Drive
    var files = DriveApp.getFiles();
  } else {
    // not the first time, pick up where we left off
    var files = DriveApp.continueFileIterator(continuationToken);
  }
  while (files.hasNext() && end.getTime() - start.getTime() <= maxTime) {
    var file = files.next();
    Logger.log(file.getName());
    end = new Date();
  }

  // Save your place by setting the token in your user properties
  if(files.hasNext()){
    var continuationToken = files.getContinuationToken();
    userProperties.setProperty('CONTINUATION_TOKEN', continuationToken);
  } else {
    // Delete the token
    PropertiesService.getUserProperties().deleteProperty('CONTINUATION_TOKEN');
  }

问题(递归迭代器)

为了检索文件夹的树状结构并获取其文件,我们必须使用递归函数。像这样的东西:

doFolders(DriveApp.getFolderById('root folder id'));
// recursive iteration
function doFolders(parentFolder) {
  var childFolders = parentFolder.getFolders();
  while(childFolders.hasNext()) {
    var child = childFolders.next();
    // do something with folder
    // go subfolders
    doFolders(child);
  }
}

但是,在这种情况下我不知道如何使用continuationToken.

Question

如何使用ContinuationToken使用递归文件夹迭代器,当我们需要抛出所有文件夹结构时?

假设

根据名称构建许多标记是否有意义id每个parent folder?


如果您尝试在文件夹上递归迭代并希望使用连续标记(大型文件夹可能需要),则您将需要一个可以存储多组连续标记的数据结构。既适用于文件和文件夹,也适用于当前层次结构中的每个文件夹。

最简单的数据结构是对象数组。

这是一个解决方案,为您提供了创建函数的模板,该函数可以递归处理文件并存储连续令牌,以便在超时时可以恢复。

  1. 简单修改一下MAX_RUNNING_TIME_MS到您想要的值(现在设置为 1 分钟)。

    您不想将其设置超过约 4.9 分钟,因为脚本可能会在此之前超时并且不存储其当前状态。

  2. 更新processFile方法对文件执行任何您想要的操作。
  3. 最后,打电话processRootFolder()并传递给它一个Folder。它会足够聪明,知道如何恢复处理文件夹。

当然,还有改进的空间(例如,它只是检查文件夹名称,看看它是恢复还是重新启动),但这对于 95% 需要在带有连续标记的文件夹上递归迭代的人来说很可能就足够了。

function processRootFolder(rootFolder) {
  var MAX_RUNNING_TIME_MS = 1 * 60 * 1000;
  var RECURSIVE_ITERATOR_KEY = "RECURSIVE_ITERATOR_KEY";

  var startTime = (new Date()).getTime();

  // [{folderName: String, fileIteratorContinuationToken: String?, folderIteratorContinuationToken: String}]
  var recursiveIterator = JSON.parse(PropertiesService.getDocumentProperties().getProperty(RECURSIVE_ITERATOR_KEY));
  if (recursiveIterator !== null) {
    // verify that it's actually for the same folder
    if (rootFolder.getName() !== recursiveIterator[0].folderName) {
      console.warn("Looks like this is a new folder. Clearing out the old iterator.");
      recursiveIterator = null;
    } else {
      console.info("Resuming session.");
    }
  }
  if (recursiveIterator === null) {
    console.info("Starting new session.");
    recursiveIterator = [];
    recursiveIterator.push(makeIterationFromFolder(rootFolder));
  }

  while (recursiveIterator.length > 0) {
    recursiveIterator = nextIteration(recursiveIterator, startTime);

    var currTime = (new Date()).getTime();
    var elapsedTimeInMS = currTime - startTime;
    var timeLimitExceeded = elapsedTimeInMS >= MAX_RUNNING_TIME_MS;
    if (timeLimitExceeded) {
      PropertiesService.getDocumentProperties().setProperty(RECURSIVE_ITERATOR_KEY, JSON.stringify(recursiveIterator));
      console.info("Stopping loop after '%d' milliseconds. Please continue running.", elapsedTimeInMS);
      return;
    }
  }

  console.info("Done running");
  PropertiesService.getDocumentProperties().deleteProperty(RECURSIVE_ITERATOR_KEY);
}

// process the next file or folder
function nextIteration(recursiveIterator) {
  var currentIteration = recursiveIterator[recursiveIterator.length-1];
  if (currentIteration.fileIteratorContinuationToken !== null) {
    var fileIterator = DriveApp.continueFileIterator(currentIteration.fileIteratorContinuationToken);
    if (fileIterator.hasNext()) {
      // process the next file
      var path = recursiveIterator.map(function(iteration) { return iteration.folderName; }).join("/");
      processFile(fileIterator.next(), path);
      currentIteration.fileIteratorContinuationToken = fileIterator.getContinuationToken();
      recursiveIterator[recursiveIterator.length-1] = currentIteration;
      return recursiveIterator;
    } else {
      // done processing files
      currentIteration.fileIteratorContinuationToken = null;
      recursiveIterator[recursiveIterator.length-1] = currentIteration;
      return recursiveIterator;
    }
  }

  if (currentIteration.folderIteratorContinuationToken !== null) {
    var folderIterator = DriveApp.continueFolderIterator(currentIteration.folderIteratorContinuationToken);
    if (folderIterator.hasNext()) {
      // process the next folder
      var folder = folderIterator.next();
      recursiveIterator[recursiveIterator.length-1].folderIteratorContinuationToken = folderIterator.getContinuationToken();
      recursiveIterator.push(makeIterationFromFolder(folder));
      return recursiveIterator;
    } else {
      // done processing subfolders
      recursiveIterator.pop();
      return recursiveIterator;
    }
  }

  throw "should never get here";
}

function makeIterationFromFolder(folder) {
  return {
    folderName: folder.getName(), 
    fileIteratorContinuationToken: folder.getFiles().getContinuationToken(),
    folderIteratorContinuationToken: folder.getFolders().getContinuationToken()
  };
}

function processFile(file, path) {
  console.log(path + "/" + file.getName());
}
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

如何将 ContinuationToken 与递归文件夹迭代器一起使用 的相关文章

  • 自动递增 ID 号 Google Apps 脚本

    我想在向工作表添加新值时自动增加 ID 我尝试从当前的 ID 列表创建一个列表 但它只计数到 5 因此当自动递增时 它只会到达一个点并为每个输入保存该数字 以下是我尝试获取 ID 号列表的方法 但它没有获取整个列表 我缺少什么 var ss
  • 适用于 Android 的 Google 云端硬盘\文档 API

    我在几个小时内将 Dropbox 与我的应用程序集成 因为 SDK 描述清晰并且有很好的使用示例 Google Drive 似乎只有一个 一刀切 的 Gdata SDK 它非常重 有很多依赖项 它使我的应用程序的大小增加了三倍 而且不是很直
  • 在网站上显示存储在 Google 云端硬盘中的文件(例如图像)

    我想知道是否可以在公共网站上访问 显示存储在 Google Drive 中的图像等文件 解决方法是获取fileId with Google Drive SDK API然后使用这个Url 文件ID 这将是您在 Google 云端硬盘中的文件
  • 使用 google apps 脚本添加大量响应

    我想制作一个脚本 添加大量 大约 1500 简历和候选人信息作为对表单的回复 我有谷歌电子表格的信息 我将其链接到表单 但我只能管理回复 即使我更改电子表格 或添加 表单中也不会发生更新 我正在添加行 但没有添加响应 那可能吗 我看到了 2
  • 通过 IOS Google Drive SDK 列出 Google Drive 的所有文件夹

    实际上我将 google drive sdk 与我的 ios 应用程序集成了 我可以通过适用于 iOS 的 google drive sdk 在 Google Drive 上上传指定文件 此外 我想提供一个功能 用于从可用文件夹中选择一个文
  • 嵌入来自谷歌驱动器的图像,没有灰色边框和缩放工具?

    I have a webpage that has an image that is stored in google drive and using the google drive embed code results in this
  • window.location.href = window.location.href 返回空白页

    我正在使用 Google App Script 创建一个网页 单击按钮后 我尝试重新加载页面 但以下操作均无效 窗口 位置 href 窗口 位置 href window location reload true 他们正在重定向到空白页面 下
  • 获取Google云端硬盘文件下载URL

    继你好世界应用程序 https developers google com picker docs 并使用文件选择器 我可以获得谷歌驱动器文件信息 我想在我的网络应用程序中获取该文件 它是一个二进制文件 的下载网址 有什么办法可以用新的 j
  • 从 Google 电子表格中的列填充 HTML 下拉菜单

    我是 gs 的新手 所以这应该不难 我有一个 Google 电子表格 其中一列中有值 假设 A 列 我使用 gs 创建了一个自定义菜单 用户将在其中选择一个选项 单击其中一个选项 新组件 将出现一个弹出窗口 其中包含一个下拉菜单 用户应从其
  • 如何编辑范围? // Google Classroom 控制 Google Apps 脚本中学生访问的权限范围

    我是一名高中老师 正在针对 Google Classroom 编写 Google Apps 脚本 我想创建一个类似于学生成绩视图的电子表格 我的学生可以使用他们的凭据进行访问 我已经成功编写了代码 这样我就可以通过在代码中显式放置学生的 I
  • 如何将值传递到 HTML 模板侧边栏?

    我的任务是更换一些现有的 Access 数据库 我想知道你们是否可以帮助我 目前 我有一个谷歌表格 https docs google com spreadsheets d 1JS5Iwx60Zk7VL8lYz6Yj7ew4eYPhl2Nk
  • 如何通过 Apps Script & Drive SDK 创建新的脚本文件

    尝试通过在 Apps 脚本中调用 Drive SDK 来创建包含文件的新项目 下面的内容到底会放在哪里UrlFetchApp要求 files id 9basdfbd 749a 4as9b b9d1 d64basdf803 name Code
  • 在 userCodeAppPanel 中看不到我的 javascript 代码

    这是来自 Google 电子表格中包含的脚本的代码 唯一的其他代码是onOpen它创建菜单和showDialog 功能 function showDialog userInterface HtmlService createHtmlOutp
  • 我可以获取特定文件的关联关键字列表吗?

    即对于执行 OCR 的图像 我希望能够获取图像上的文本列表 使用 SDK 可以实现吗 如果是这样 如何 如果没有 是否有任何关于使用谷歌的 OCR 来获取图像中的单词的建议 当你create https developers google
  • 使用 google-drive-ruby gem 在 google 云端硬盘中创建文件夹

    我知道这里提出了类似的问题 但是我仍然无法完成这项工作 因为我的情况有点不同 我希望能够使用以下命令在谷歌驱动器中创建一个文件夹谷歌驱动器红宝石宝石 https github com gimite google drive ruby 根据谷
  • 测量填写部分的时间 - 谷歌表单

    我正在尝试使用谷歌表单进行研究调查问卷 对于某些部分 我想自动测量用户填写所需的时间 谷歌表单中没有这样的选项 我尝试复制表单源 并用 javascript 填充时间 但它不起作用 跨源问题 未能成功托管复制的表单 如何做到 我如何衡量回答
  • 如何使用 Google Apps 脚本添加指向电子表格单元格的链接

    可以通过用户界面向 Google 电子表格中的单元格添加 链接 我想使用 Google Apps 脚本执行相同的操作 我本以为 Range 类上有一种方法可以实现这一点 但看不到 有谁知道如何做到这一点 截至 2020 年 6 月 可以选择
  • 模板化 HTML 脚本中的换行符

    如果我有一个 HTML 文件 test html p p 和一个脚本函数 var t HtmlService createTemplateFromFile test html t str test nstring var content t
  • IOS 无法从 Google Drive 获取文件

    这是我的代码 GTLQueryDrive query GTLQueryDrive queryForFilesList query q NSString stringWithFormat IN parents root self driveS
  • 如何在表单提交时运行 Appscript?

    我正在尝试创建当用户完成表单提交时重定向到网络应用程序的 Google 表单 我查过谷歌开发者文档 https developers google com apps script guides triggers 但我看不到一种简单的方法来做

随机推荐

  • 如何在移动设备上进行画布绘图

    我的画布绘图界面在桌面上完美运行 但在 iPhone 上无法运行 当我尝试画画时 它只会在我拇指所在的地方画出一个点 当我拖动拇指时 没有线条 页面继续滚动 Code var clearButton document getElementB
  • 我有这个错误“#1273 - 未知排序规则:'utf8mb4_0900_ai_ci'”

    CREATE TABLE payment methods payment method id tinyint 4 NOT NULL AUTO INCREMENT name varchar 50 NOT NULL PRIMARY KEY pa
  • 在具有 Root 权限的 Android 4.4.2 中启用 KioskMode

    我能够通过终止 KitKat 之前的版本来启用 kiosk 模式com android systemui过程 无论如何 这似乎在 KitKat 版本中不起作用 终止进程后 整个屏幕卡住了 我无法按任何按钮 在检查了 Play 商店中的类似应
  • 第二次单击时从元素中删除活动和焦点

    我正在尝试制作一个带有信息的交互式地图 当您单击一个点时 它会调整大小并显示一些联系人 这是因为该元素获得了 active and focus伪类 有什么方法可以在第二次单击元素时从元素中删除伪类吗 实际上 是否可以在再次单击元素时关闭元素
  • RAISERROR―如何与SqlException区分?

    我有一些 3 4 个存储过程 如果需要的话我可以修改它们 使用RAISERROR通知我的应用程序数据库方面的一些致命错误 其中一些存储过程是从 C 端执行的ExecuteNonQuery 而其他则执行ExecuteReader 目前 我将这
  • 将所有包含内容放在一个头文件中是个好主意吗?

    对于 C 来说 放入 C 头文件中的内容的最佳实践是什么 将跨多个源文件的程序使用的所有包含内容放在一个头文件中是否有用 几乎每个文件 即 stdio h 中都使用的包含怎么样 不会 它只会增加麻烦和开销 作为维护者 你面临的最大的痛苦之一
  • Maven - 未解决部署在 Artifactory 上的工件的传递依赖关系

    我有两个项目 A 和 B 其中 A 依赖于 B 我将 B 打包为 jar 并将其部署在 maven 服务器 artifactory 上 然后将该 jar 包含在 pom 文件中作为项目 A 的正常依赖项 B 的 jar 文件显示在项目 A
  • 使用 Google Apps 脚本修改绘图

    有没有人找到使用 Google Apps 脚本创建或更改绘图的支持 我已经浏览过谷歌文档 但我没有看到任何绘画课程 我发现了如何构建用户界面元素 但不是图纸 我希望将绘图作为文档或电子表格的一部分 但独立的绘图就足够了 直到今天 还无法执行
  • shell_exec 无需等待输出[重复]

    这个问题在这里已经有答案了 可能的重复 PHP 中的异步 shell 执行 有没有办法使用 shell exec 而不等待命令完成 我想运行一个相当慢 复杂的程序 至少需要 10 分钟才能完成 我想通过 shell exec 或类似的东西来
  • 如何优雅地返回默认初始化的对象?

    我有一个如下所示的课程 class VeryVeryVeryLongTypeName bool is ok VeryVeryVeryLongTypeName is ok false VeryVeryVeryLongTypeName f Ve
  • 如何从 bootRun 传递 JVM 选项

    我正在开发与远程主机通信的简单 Spring Web 应用程序 我想在公司代理后面在本地测试它 我使用 Spring Boot gradle 插件 问题是如何指定 JVM 的代理设置 我尝试了几种方法来做到这一点 gradle Dhttp
  • 使用 Apache Beam 按键处理事件的总排序

    问题背景 我正在尝试从实时流中生成每个键的事件项的总 线性 顺序 其中顺序是事件时间 源自事件有效负载 Approach 我曾尝试使用流式传输来实现此目的 如下所示 1 设置一个非重叠的顺序窗口 例如时长5分钟 2 建立允许的迟到 可以丢弃
  • 自动日期/时间解析器,无需指定格式[关闭]

    Closed 此问题正在寻求书籍 工具 软件库等的推荐 不满足堆栈溢出指南 目前不接受答案 我正在寻找一个java库 它可以将字符串解析为POJO而不指定格式 我研究过POjava 还有其他库可以做类似的事情吗 DateTime dateT
  • 为什么Spark要将Map阶段的输出保存到本地磁盘?

    我试图深入了解 Spark Shuffle 过程 当我开始阅读时 我遇到了以下几点 Spark 完成后将 Map 任务 ShuffleMapTask 输出直接写入磁盘 我想了解以下关于 Hadoop MapReduce 的内容 如果Map
  • 在 Meteor.js 中,如何让两个开发项目使用同一个 Mongo 实例?

    我希望两个单独的应用程序使用相同的 Mongo DB 实例 并且由于我同时开发它们 因此我希望能够共享相同的开发数据库实例 我意识到 Meteor 的每个实例都必须在它自己的端口上运行 有没有办法像系统版本的MongoDB一样强制meteo
  • 当每个请求的应用程序 ID 和应用程序密钥都不同时,使用omniauth-facebook 吗?

    The omn iauth facebook自述文件提到了如何在初始化程序中设置它以及如何设置选项 例如scope仅根据请求 我想知道是否也可以为每个请求设置应用程序 ID 和应用程序密钥 你可以这样做 在您的omniauth rb 上 执
  • 在 Service Worker / fetch() 中识别 HTTP 304

    我构建了一个服务工作人员 它始终使用缓存中的数据进行响应 然后在后台向服务器发送请求 如果服务器响应HTTP 304 not modified一切都很好 如果服务器响应HTTP 200 这意味着数据已更改 新文件已放入缓存中 同时通知用户并
  • 初始化 ST-Link 设备时出错 - 无法连接到设备

    我目前正在使用 ST Link 调试器对我的 STM32F3 Discovery 板进行编程 我使用的IDE是Atollic TrueStudio 5 5 2 现在我面临一个非常奇怪的问题 那就是我不断收到消息 初始化 ST Link 设备
  • Selenium WebDriver (2.25) 超时不起作用

    我想我已经阅读了 Stack Overflow 上的所有 Selenium 超时问题 但隐式或显式超时在我的 Selenium webdriver 2 25 Python 2 7 绑定 中都不起作用 并且 no timeout here 行
  • 如何将 ContinuationToken 与递归文件夹迭代器一起使用

    由于 Drive API 配额 服务配额以及脚本执行时间的限制6 min将 Google Drive 文件操作拆分为多个块通常很重要 我们可以用属性服务储藏continuationToken for 文件夹迭代器 or 文件迭代器 这样我们