如何用Batch Request API批量导出100张Slides为PNG?
解决方案
一、将PNG导出转换为Batch Request
Google Batch API可将多个API请求打包为一个请求发送,减少网络往返次数,规避单次请求过多导致的超时问题。以下是在App Script中实现批量导出幻灯片为PNG的具体步骤:
1. 批量预处理幻灯片
先完成所有幻灯片副本的创建、文本与图片填充,统一收集导出所需参数:
function prepareAllTickets(rows) { const templateFile = DriveApp.getFileById(TEMPLATE_SLIDE_ID); const parentFolder = templateFile.getParents().next(); // 提前检查并创建images文件夹,避免重复操作 let imagesFolder = parentFolder.getFoldersByName('images').hasNext() ? parentFolder.getFoldersByName('images').next() : parentFolder.createFolder('images'); const exportTasks = []; for (const row of rows) { // 复制模板并直接命名,减少后续重命名操作 const copySlide = templateFile.makeCopy(`Ticket for ${row[2]}`, parentFolder); const workingSlides = SlidesApp.openById(copySlide.getId()); const slide = workingSlides.getSlides()[0]; // 一次遍历完成所有文本与图片替换 slide.getPageElements().forEach(pageElement => { if (pageElement.getPageElementType() === SlidesApp.PageElementType.SHAPE) { const shapeText = pageElement.asShape().getText(); shapeText.replaceAllText("{{FETLIFEHANDLE}}", row[2].toString()); shapeText.replaceAllText("{{POSITION}}", row[3].toString()); shapeText.replaceAllText("{{TICKETNO}}", row[0].toString()); } else if (pageElement.getPageElementType() === SlidesApp.PageElementType.IMAGE) { const img = pageElement.asImage(); if (img.getTitle() === "{{QRCODE}}") { img.replace(row[6].toString()); } } }); workingSlides.saveAndClose(); // 收集导出任务参数 exportTasks.push({ slidesID: copySlide.getId(), slideID: slide.getObjectId(), filename: `Ticket-${row[2]}.png`, imagesFolder: imagesFolder }); // 不需要保留幻灯片副本的话,直接移入回收站 // copySlide.setTrashed(true); } return exportTasks; }
2. 构造并发送Batch Request
将所有导出请求打包为Batch API请求发送:
function batchExportPNG(exportTasks) { const token = ScriptApp.getOAuthToken(); const boundary = `batch_${Utilities.getUuid()}`; let batchBody = []; for (const task of exportTasks) { const exportUrl = `https://docs.google.com/presentation/d/${task.slidesID}/export/png?id=${task.slidesID}&pageid=${task.slideID}`; // 构造单个子请求的头部与内容 batchBody.push( `--${boundary}`, "Content-Type: application/http", "Content-Transfer-Encoding: binary", "", `GET ${exportUrl} HTTP/1.1`, `Authorization: Bearer ${token}`, "Host: docs.google.com", "" ); } // 添加请求结束标记 batchBody.push(`--${boundary}--`); const payload = batchBody.join("\r\n"); const options = { method: "POST", headers: { "Content-Type": `multipart/mixed; boundary=${boundary}`, "Authorization": `Bearer ${token}` }, payload: payload, muteHttpExceptions: true }; const response = UrlFetchApp.fetch("https://www.googleapis.com/batch", options); const responseBody = response.getContentText(); // 解析响应并保存每个PNG文件 const parts = responseBody.split(`--${boundary}`); for (let i = 1; i < parts.length - 1; i++) { const part = parts[i]; const [headerPart, bodyPart] = part.split("\r\n\r\n", 2); if (!headerPart.includes("200 OK")) continue; const blob = Utilities.newBlob(Utilities.base64Decode(bodyPart.trim()), "image/png", exportTasks[i-1].filename); exportTasks[i-1].imagesFolder.createFile(blob); } }
3. 调用批量处理函数
在主函数中串联两个步骤:
function processBatchTickets(rows) { const exportTasks = prepareAllTickets(rows); batchExportPNG(exportTasks); }
二、其他加速代码的方法
除了Batch Request,还可通过以下方式优化性能:
- 合并Slides操作:原代码每个形状重复调用3次
replaceAllText,改为一次遍历完成所有文本替换,减少API调用次数。 - 用Slides API替代SlidesApp:使用Slides API的
batchUpdate方法,一次性提交所有文本替换、图片更新请求,大幅降低网络往返开销。 - 减少Drive API调用:复制模板时直接指定目标文件夹与名称,避免后续
getParents()、setName()的额外操作。 - 启用V8运行时:确保项目使用V8引擎,它比旧引擎运行更快,支持现代JS语法。
- 批量清理临时文件:导出PNG后统一删除幻灯片副本,减少Drive操作负载。
内容的提问来源于stack exchange,提问作者Abby Cottontail
相关产品推荐
相关产品推荐

