Google apps script 正确使用DriveApp.continueFileIterator(continuationToken)

Google apps script 正确使用DriveApp.continueFileIterator(continuationToken),google-apps-script,google-drive-api,Google Apps Script,Google Drive Api,我已经编写了一个脚本来遍历Google Drive文件夹中的大量文件。由于我正在处理这些文件,它超过了最大执行时间。当然,我在脚本中写入了使用DriveApp.continueFileIterator(continuationToken):令牌存储在项目属性中,当脚本运行时,它会检查是否有令牌,如果有,它会从令牌创建FileIterator,如果没有,它会重新启动 我发现,即使脚本使用continuation标记重新启动,它仍然从迭代开始时开始,试图再次处理相同的文件,这会浪费后续执行的时间。我

我已经编写了一个脚本来遍历Google Drive文件夹中的大量文件。由于我正在处理这些文件,它超过了最大执行时间。当然,我在脚本中写入了使用DriveApp.continueFileIterator(continuationToken):令牌存储在项目属性中,当脚本运行时,它会检查是否有令牌,如果有,它会从令牌创建FileIterator,如果没有,它会重新启动

我发现,即使脚本使用continuation标记重新启动,它仍然从迭代开始时开始,试图再次处理相同的文件,这会浪费后续执行的时间。我是否错过了一些重要的东西,比如在命令或方法中,让它从停止的地方开始?我是否应该在不同阶段更新延续令牌,而不考虑while(contents.hasNext())循环

下面是精简后的示例代码,让您了解:

function listFilesInFolder() {
  var id= '0fOlDeRiDg';
  var scriptProperties = PropertiesService.getScriptProperties();
  var continuationToken = scriptProperties.getProperty('IMPORT_ALL_FILES_CONTINUATION_TOKEN');
  var lastExecution = scriptProperties.getProperty('LAST_EXECUTION');
  if (continuationToken == null) {
    // first time execution, get all files from drive folder
    var folder = DriveApp.getFolderById(id);
    var contents = folder.getFiles();
    // get the token and store it in a project property
    var continuationToken = contents.getContinuationToken();
    scriptProperties.setProperty('IMPORT_ALL_FILES_CONTINUATION_TOKEN', continuationToken);
  } else {
    // we continue to import from where we left
    var contents = DriveApp.continueFileIterator(continuationToken);
  }
  var file;
  var fileID;
  var name;
  var dateCreated;

  while(contents.hasNext()) {
    file = contents.next();
    fileID = file.getId();
    name = file.getName();
    dateCreated = file.getDateCreated();
    if(dateCreated > lastExecution) {
      processFiles(fileID);
    }
  }
  // Finished processing files so delete continuation token
  scriptProperties.deleteProperty('IMPORT_ALL_FILES_CONTINUATION_TOKEN');
  var currentExecution = Utilities.formatDate(new Date(), "GMT", "yyyy-MM-dd HH:mm:ss");
  scriptProperties.setProperty('LAST_EXECUTION',currentExecution);
};

你的约会比较不会按你的方式进行

var currentExecution = Utilities.formatDate(new Date(), "GMT", "yyyy-MM-dd HH:mm:ss");
将存储
“2014-04-18 08:32:01”
,而文件日期
file.getDateCreated()
将返回一个日期对象,使用
对这些对象进行比较时将始终返回false

因此,我建议您将时间存储为时间戳(因为您无法存储日期对象),然后将其与文件创建日期的时间戳进行比较

// stored time stamp
var lastExecution = scriptProperties.getProperty('LAST_EXECUTION');

…

dateCreated = file.getDateCreated().getTime();

…

var currentExecution = new Date().getTime();
scriptProperties.setProperty('LAST_EXECUTION',currentExecution);

这种比较会像你预期的那样起作用。

正如乔纳森所说,你比较日期是错误的。但这不是你剧本的主要问题,也不是你问的问题

您所犯的主要错误是,在执行循环之前,无法保存延续令牌。当您获得令牌时,它会保存您当时所在的位置,如果您随后继续迭代,则不会保存该令牌,您将在稍后重复这些步骤,就像您正在经历的那样

若要稍后获取令牌,您不能让脚本因错误而终止。您必须测量在5分钟内可以处理多少文件,并在此之前手动停止脚本,以便有机会保存令牌

以下是正确的方法:

函数listFilesInFolder(){
var MAX_FILES=20;//使用安全值,不要贪心
变量id='文件夹id';
var scriptProperties=PropertiesService.getScriptProperties();
var lastExecution=scriptProperties.getProperty('LAST_EXECUTION');
if(lastExecution==null)
最后执行=“”;
var continuationToken=scriptProperties.getProperty('IMPORT_ALL_FILES_CONTINUATION_TOKEN');
变量迭代器=continuationToken==null?
DriveApp.getFolderById(id).getFiles():DriveApp.continueFileInterator(continuationToken);
试试{
对于(var i=0;ilastExecution)
进程文件(文件);
}
}捕捉(错误){
Logger.log(err);
}
if(iterator.hasNext()){
scriptProperties.setProperty('IMPORT_ALL_FILES_CONTINUATION_TOKEN',iterator.getContinuationToken());
}else{//已完成文件处理,因此删除继续标记
scriptProperties.deleteProperty('IMPORT_ALL_FILES_CONTINUATION_TOKEN');
setProperty('LAST_EXECUTION',formatDate(new Date());
}
}
函数formatDate(日期){返回实用程序.formatDate(日期,“GMT”,“yyyy-MM-dd HH:MM:ss”);}
函数processFile(文件){
var id=file.getId();
var name=file.getName();
//您的处理。。。
Logger.log(名称);
}

无论如何,有可能在运行之间创建了一个文件,但在继续迭代时却没有得到它。然后,通过在上次运行后保存执行时间,您也可能在下次运行时错过它。我不知道您的用例,如果最终重新处理一些文件或丢失一些文件是可以接受的。如果两种情况都不能满足,那么我看到的唯一解决方案是保存所有已处理文件的ID。您可能需要将它们存储在驱动器文件中,因为PropertiesService对于太多ID来说可能太小。

它是在第一次执行时超时还是完成?