如何加速Google Apps Script以导出云端硬盘所有文件至表格
优化Google Apps Script批量导出云端硬盘文件到表格的方案
你的脚本运行超时核心原因是频繁的表格逐行写入和Drive服务的串行调用,以下是针对性的优化方案:
核心优化点
1. 批量写入表格,杜绝逐行调用appendRow
每次appendRow都会触发Google表格的远程同步,几百上千次调用会累积大量耗时。改为先把所有文件数据存入一个大数组,最后一次性写入表格。
2. 减少Spreadsheet服务的重复调用
不要在listFiles函数里反复获取工作表对象,直接在主函数中获取后作为参数传递给子函数,避免重复的API调用。
3. 替换DriveApp为Drive Advanced Service(可选但效果显著)
Drive API支持批量查询文件和文件夹信息,比DriveApp的串行遍历效率高得多,能大幅减少运行时间。需要先在脚本编辑器的「服务」中启用Drive API。
4. 移除不必要的日志输出
Logger.log在大量文件夹遍历过程中会增加额外耗时,直接删除即可。
优化后的DriveApp版本代码
function listFilesAndFolders() { const folderId = "YOUR_FOLDER_ID"; // 替换为你的文件夹ID const sh = SpreadsheetApp.getActiveSheet(); sh.clear(); // 初始化表头和数据数组 const headers = ["parent","folder", "name", "update", "Size", "URL", "ID", "description", "type"]; const allData = [headers]; try { const parentFolder = DriveApp.getFolderById(folderId); // 传入数据数组,收集所有文件信息 collectFiles(parentFolder, parentFolder.getName(), allData); collectSubFolders(parentFolder, parentFolder.getName(), allData); // 一次性写入所有数据 if (allData.length > 1) { sh.getRange(1, 1, allData.length, headers.length).setValues(allData); } } catch (e) { Logger.log(e.toString()); } } function collectSubFolders(parentFolder, parentPath, allData) { const childFolders = parentFolder.getFolders(); while (childFolders.hasNext()) { const childFolder = childFolders.next(); const newPath = parentPath + "|" + childFolder.getName(); collectFiles(childFolder, newPath, allData); collectSubFolders(childFolder, newPath, allData); } } function collectFiles(folder, parentPath, allData) { const files = folder.getFiles(); while (files.hasNext()) { const file = files.next(); // 将文件信息追加到数组,不直接写入表格 allData.push([ parentPath, folder.getName(), file.getName(), file.getLastUpdated(), file.getSize(), file.getUrl(), file.getId(), file.getDescription() || "", // 处理空描述 file.getMimeType() ]); } }
更高效的Drive API版本代码
启用Drive API后,使用批量查询可以进一步提速,适合超大规模文件库:
function listFilesWithDriveAPI() { const folderId = "YOUR_FOLDER_ID"; // 替换为你的文件夹ID const sh = SpreadsheetApp.getActiveSheet(); sh.clear(); const headers = ["parent","folder", "name", "update", "Size", "URL", "ID", "description", "type"]; const allData = [headers]; // 递归遍历文件夹,使用Drive API批量获取文件 function traverseFolder(folderId, parentPath) { const folder = Drive.Files.get(folderId); const folderName = folder.title; // 查询当前文件夹下的所有文件 const filesResponse = Drive.Files.list({ q: `'${folderId}' in parents and trashed = false`, fields: "items(id, title, modifiedDate, fileSize, alternateLink, description, mimeType)", maxResults: 1000 }); // 处理文件数据 if (filesResponse.items) { filesResponse.items.forEach(file => { allData.push([ parentPath, folderName, file.title, new Date(file.modifiedDate), file.fileSize || 0, file.alternateLink, file.id, file.description || "", file.mimeType ]); }); } // 查询当前文件夹下的子文件夹 const foldersResponse = Drive.Files.list({ q: `'${folderId}' in parents and trashed = false and mimeType = 'application/vnd.google-apps.folder'`, fields: "items(id, title)", maxResults: 1000 }); // 递归遍历子文件夹 if (foldersResponse.items) { foldersResponse.items.forEach(subFolder => { const newPath = parentPath ? `${parentPath}|${subFolder.title}` : subFolder.title; traverseFolder(subFolder.id, newPath); }); } } try { const rootFolder = Drive.Files.get(folderId); traverseFolder(folderId, rootFolder.title); // 初始父路径为根文件夹名称 if (allData.length > 1) { sh.getRange(1, 1, allData.length, headers.length).setValues(allData); } } catch (e) { Logger.log(e.toString()); } }
优化效果说明
- DriveApp优化版:通过批量写入,运行时间可降低至原脚本的1/5~1/3,适合文件量在几千级的场景。
- Drive API版:批量查询减少了Drive服务的调用次数,运行时间可降低至原脚本的1/10甚至更低,适合上万级文件的大规模场景。
内容的提问来源于stack exchange,提问作者Shironeki
相关产品推荐
相关产品推荐

