You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何在Google Apps Script中读取压缩包内文件名并优化性能?

问题:优化Google Drive压缩包文件名读取效率

我需要读取Google Drive中压缩文件夹内的文件名,截取前17个字符创建新文件夹。现有代码能实现需求,但必须先把文件解压到临时文件夹才能读取文件名,压缩包内有800+文件,运行速度极慢。

现有代码逻辑:

  • 检查目标文件夹是否存在以昨日日期命名的文件夹,不存在则创建
  • 查找含昨日日期的压缩包,解压文件到Temp文件夹
  • 截取文件名前17位,检查日期文件夹下是否存在对应名称的子文件夹,不存在则创建
  • 删除临时文件

现有代码:

function CreateNewImageFolder() {
  const optionalArgs={supportsAllDrives: true};                                              // 支持共享驱动器
  const timezone = Session.getScriptTimeZone();                                              // 获取脚本时区
  const afId = 'archivefolderID';                                           // "Image_Archive"文件夹ID
  const aDest = DriveApp.getFolderById(afId);                                                // 获取"Image_Archive"文件夹
  const op20Id = 'fixedfolderW/allfilenames';                                         // 存储所有压缩包的文件夹ID
  const op20 = DriveApp.getFolderById(op20Id);                                               // 获取压缩包所在文件夹
  const tId = 'tempfolderID';                                            // 临时文件夹ID
  const temp = DriveApp.getFolderById(tId);                                                  // 获取临时文件夹
  
  var yday = Utilities.formatDate(GetYesterday(1), timezone, "MM-dd");                       // 昨日日期(MM-dd格式,用于搜索压缩包)
  var yyear = Utilities.formatDate(GetYesterday(1), timezone, "yyyy-MM-dd");                     // 昨日日期(yyyy-MM-dd格式,用于创建日期文件夹)
    Logger.log("Yesterday: %s", yday);

//// 检查并创建昨日日期文件夹 ///
  var datefold = aDest.searchFolders("title contains '"+yyear+"'");                           // 搜索是否存在日期文件夹
    if (datefold.hasNext()===true) {                                                        
      while (datefold.hasNext()) {
        var dfolder = datefold.next();
        Logger.log("Folder %s already exists", dfolder.getName());
      }
    } else{
        var dfolder=aDest.createFolder(yyear);                                                // 不存在则创建
          Logger.log("New Date Folder Name: %s", dfolder.getName());
      }
    var dfoldId = dfolder.getId();
    var vDest = DriveApp.getFolderById(dfoldId);
      Logger.log("New Folder Destination: %s", vDest.getName());

//// 遍历压缩包文件 ////
  var zfi = op20.searchFiles("title contains '"+yday+"'");                                    // 搜索昨日的压缩包
    while (zfi.hasNext()){                                                                    // 遍历压缩包迭代器
      var file = zfi.next();                                                                  // 获取当前压缩包
        Logger.log("Zip Folder: %s", file.getName());
      var fileBlob = file.getBlob();                                                         // 获取压缩包Blob
      fileBlob.setContentType("application/zip");                                             
      var unZippedfile = Utilities.unzip(fileBlob);                                          // 解压压缩包

  //// 遍历解压后的文件 ////
      for (i=0; i<unZippedfile.length; i++) {                                                
        var uzf = temp.createFile(unZippedfile[i]);                                          // 在临时文件夹创建解压后的文件
        var fileName = uzf.getName().substring(0, 17);                                           // 截取文件名前17位
          Logger.log("unzipped File Name: %s", fileName);

    //// 检查并创建子文件夹 ////    
        var vfold = vDest.searchFolders("title contains '"+fileName+"'");                      // 搜索是否存在对应子文件夹
        if (vfold.hasNext()===true) {    
          while (vfold.hasNext()) {
          var vfolder = vfold.next();
          Logger.log("Folder %s already exists", vfolder.getName());
          }
        } else{
          var vfolder=vDest.createFolder(fileName);                                                // 不存在则创建
            Logger.log("New Folder Name: %s", vfolder.getName());
          }
        uzf.setTrashed(true); // 删除临时文件
      }
    }
}

示例场景:
压缩包路径:根目录 > Image_Archive > 站点 > 摄像头 > 日期 > 'zippedfolderName_2022_10_23',内有多个以17位唯一编号开头的图片文件。
期望输出路径:根目录 > Image_Archive > 昨日日期命名文件夹 > 17位编号命名子文件夹


优化方案

核心思路是跳过临时文件创建步骤,直接从Utilities.unzip()返回的Blob对象中获取文件名,无需写入Drive临时文件夹,避免大量Drive API调用的性能损耗。

优化后的代码:

function CreateNewImageFolder() {
  const optionalArgs = {supportsAllDrives: true};
  const timezone = Session.getScriptTimeZone();
  const afId = 'archivefolderID'; // "Image_Archive"文件夹ID
  const aDest = DriveApp.getFolderById(afId);
  const op20Id = 'fixedfolderW/allfilenames'; // 存储所有压缩包的文件夹ID
  const op20 = DriveApp.getFolderById(op20Id);
  
  // 获取昨日日期的两种格式
  const yesterday = GetYesterday(1);
  const yday = Utilities.formatDate(yesterday, timezone, "MM-dd");
  const yyear = Utilities.formatDate(yesterday, timezone, "yyyy-MM-dd");
  Logger.log("昨日日期(MM-dd): %s", yday);

  // 创建/获取昨日日期文件夹(精确匹配,避免模糊搜索的冗余结果)
  let dfolder = null;
  const dateFolders = aDest.searchFolders(`title = '${yyear}'`);
  if (dateFolders.hasNext()) {
    dfolder = dateFolders.next();
    Logger.log("日期文件夹 %s 已存在", dfolder.getName());
  } else {
    dfolder = aDest.createFolder(yyear);
    Logger.log("创建新日期文件夹: %s", dfolder.getName());
  }
  const vDest = dfolder;
  Logger.log("目标文件夹: %s", vDest.getName());

  // 获取昨日的压缩包文件
  const zipFiles = op20.searchFiles(`title contains '${yday}'`);
  // 用Set存储已处理的文件名,避免重复检查和创建文件夹
  const processedNames = new Set();

  while (zipFiles.hasNext()) {
    const zipFile = zipFiles.next();
    Logger.log("处理压缩包: %s", zipFile.getName());
    
    const zipBlob = zipFile.getBlob();
    zipBlob.setContentType("application/zip");
    const unzippedBlobs = Utilities.unzip(zipBlob);

    // 遍历解压后的Blob,直接读取文件名
    for (const blob of unzippedBlobs) {
      const fullName = blob.getName();
      const folderName = fullName.substring(0, 17);
      
      // 跳过已处理过的文件名,减少重复操作
      if (processedNames.has(folderName)) continue;
      processedNames.add(folderName);

      // 精确检查子文件夹是否存在
      const existingFolders = vDest.searchFolders(`title = '${folderName}'`);
      if (!existingFolders.hasNext()) {
        const newFolder = vDest.createFolder(folderName);
        Logger.log("创建新子文件夹: %s", newFolder.getName());
      } else {
        Logger.log("子文件夹 %s 已存在", folderName);
      }
    }
  }
}

// 补充GetYesterday函数(如果原有代码未定义)
function GetYesterday(offset) {
  const date = new Date();
  date.setDate(date.getDate() - offset);
  return date;
}

优化效果说明

  1. 移除临时文件操作:不再创建和删除临时文件,直接从Blob对象读取文件名,减少大量Drive API调用,速度提升明显
  2. 去重处理:使用Set存储已处理的文件名,避免对同一文件夹名称重复执行搜索检查
  3. 精确搜索匹配:将title contains改为title =,减少不必要的搜索结果遍历,提升搜索效率

内容的提问来源于stack exchange,提问作者AaronS

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.15 22:10:27