如何在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; }
优化效果说明
- 移除临时文件操作:不再创建和删除临时文件,直接从Blob对象读取文件名,减少大量Drive API调用,速度提升明显
- 去重处理:使用Set存储已处理的文件名,避免对同一文件夹名称重复执行搜索检查
- 精确搜索匹配:将
title contains改为title =,减少不必要的搜索结果遍历,提升搜索效率
内容的提问来源于stack exchange,提问作者AaronS
相关产品推荐
相关产品推荐

