如何优化处理Google Drive 1200+图片的Google Scripts脚本,避免运行超时
Google Apps Script 批量提取图片元数据优化方案
原脚本核心性能瓶颈
- 逐行调用
appendRow写入表格:每次写入都是单独的IO请求,1200次写入会浪费大量时间在网络交互上 - 逐个文件调用
Drive.Files.get拉取元数据:单文件API请求延迟高,大量重复请求极易触发超时 - 未过滤非图片文件:所有类型文件都会尝试查询图片元数据,既浪费资源也容易触发报错
- 存在逻辑bug:
listAll & files.hasNext()是按位与操作,应为&&逻辑与;getFolderTree中调用getChildFolders时第二个参数错误传了未定义的parent变量,应为parentFolder
具体优化措施
- 批量写入替代逐行写入:先将所有结果存入二维数组,所有数据处理完成后一次性写入表格,可将IO请求从1200+次降到1次
- 批量拉取元数据:先递归收集所有目标文件夹ID,再调用一次
Drive.Files.list批量拉取所有图片的元数据,将API请求从1200+次降到个位数 - 提前过滤图片文件:API查询时直接指定MIME类型为图片,避免无效处理
- 启用V8运行时:在脚本编辑器的「项目设置」中勾选「启用Chrome V8运行时」,可大幅提升脚本执行速度
- 限制返回字段:调用Drive API时指定仅返回需要的字段,减少返回数据体积,降低请求耗时
优化后完整代码
// 替换为你的目标文件夹ID const FOLDER_ID = "替换为你自己的文件夹ID"; // 主函数:列出所有图片元数据并写入表格 function listAllImages() { try { // 1. 递归收集所有子文件夹ID const allFolderIds = []; const parentFolder = DriveApp.getFolderById(FOLDER_ID); collectFolderIds(parentFolder, allFolderIds); // 加入根文件夹ID allFolderIds.push(FOLDER_ID); // 2. 批量查询所有文件夹下的图片元数据 const allImages = []; let pageToken = null; // 构造查询条件:文件在目标文件夹内,且为图片类型 const query = `(${allFolderIds.map(id => `'${id}' in parents`).join(" or ")}) and mimeType contains 'image/' and trashed = false`; do { const res = Drive.Files.list({ q: query, fields: "files(id, name, webViewLink, parents, imageMediaMetadata)", supportsAllDrives: true, includeItemsFromAllDrives: true, pageToken: pageToken, maxResults: 1000 // 单次最多拉1000条,超过的话自动分页 }); if (res.files && res.files.length > 0) { allImages.push(...res.files); } pageToken = res.nextPageToken; } while (pageToken); // 3. 构造路径映射表:文件夹ID对应完整路径 const folderPathMap = new Map(); buildFolderPathMap(parentFolder, parentFolder.getName(), folderPathMap); // 4. 处理所有图片数据,存入二维数组 const output = [["Path", "FileName", "Link", "Width", "Height"]]; allImages.forEach(img => { const parentFolderId = img.parents[0]; const folderPath = folderPathMap.get(parentFolderId) || "未知路径"; const width = img.imageMediaMetadata?.width || "无数据"; const height = img.imageMediaMetadata?.height || "无数据"; output.push([ folderPath, img.name, img.webViewLink, width, height ]); }); // 5. 一次性写入表格 const sheet = SpreadsheetApp.getActiveSheet(); sheet.clear(); sheet.getRange(1, 1, output.length, output[0].length).setValues(output); } catch (e) { Logger.log("错误:" + e.toString()); } } // 递归收集所有子文件夹ID function collectFolderIds(parentFolder, idList) { const childFolders = parentFolder.getFolders(); while (childFolders.hasNext()) { const child = childFolders.next(); idList.push(child.getId()); collectFolderIds(child, idList); } } // 递归构建文件夹ID到完整路径的映射 function buildFolderPathMap(parentFolder, parentPath, pathMap) { pathMap.set(parentFolder.getId(), parentPath); const childFolders = parentFolder.getFolders(); while (childFolders.hasNext()) { const child = childFolders.next(); const childPath = `${parentPath} / ${child.getName()}`; buildFolderPathMap(child, childPath, pathMap); } }
使用注意事项
- 首次运行需要授权脚本访问Google Drive和Google Sheets权限
- 确保脚本已经启用「Drive API」:在脚本编辑器点击「服务」→添加「Drive API」即可
- 1200张图片的处理耗时通常在1分钟以内,远低于6分钟的执行时间限制,不会触发超时
内容的提问来源于stack exchange,提问作者Adrian
相关产品推荐
相关产品推荐

