合并Docx文件为PDF时JavaScript运行时意外退出问题
问题分析与解决方案
错误根源
- URL匹配范围不足:原正则仅适配Drive文件URL(
/file/d/),但输入的URL包含Google Docs文档(/document/d/),导致无法提取对应文件ID,后续流程直接出错。 - 未覆盖Google Docs类型:Google Docs的MIME类型为
application/vnd.google-apps.document,原代码未处理该类型,无法完成格式转换。 - Blob创建逻辑异常:原代码中
[...new Int8Array(bytes)]的转换方式可能导致数据损坏,触发运行时意外退出。
修改后的完整代码
async function newMain() { // 替换为你的目标文件夹ID const destinationFolderId = "your-folder-id"; const destinationFolder = DriveApp.getFolderById(destinationFolderId); // 从表格读取URL列表(需确保sheet变量已提前定义) const urls = sheet.getRange(2, 2).getValue().toString().split(","); // 提取文件ID:兼容Google Docs和Drive文件URL const ids = urls.map(url => { const matches = url.match(/(?:\/file\/d\/|\/document\/d\/)([^\/]+)\/edit/); return matches ? matches[1] : null; }).filter(id => id !== null); // 过滤无效ID // 批量获取PDF格式数据 const pdfDatas = await Promise.all(ids.map(async id => { const file = DriveApp.getFileById(id); const mimeType = file.getMimeType(); let pdfBlob; switch(mimeType) { case 'application/vnd.openxmlformats-officedocument.wordprocessingml.document': // 转换docx为PDF并清理临时文件 const tempFile = Drive.Files.insert({}, file.getBlob(), {convert: true}); pdfBlob = DriveApp.getFileById(tempFile.id).getBlob(); Drive.Files.remove(tempFile.id); break; case 'application/pdf': pdfBlob = file.getBlob(); break; case 'application/vnd.google-apps.document': // 直接导出Google Docs为PDF pdfBlob = Drive.Files.export(id, MimeType.PDF); break; default: console.log(`跳过不支持的文件类型:${mimeType}`); return null; } return pdfBlob ? new Uint8Array(pdfBlob.getBytes()) : null; })).then(datas => datas.filter(data => data !== null)); // 过滤无效数据 // 加载pdf-lib库 const cdnjs = "https://cdn.jsdelivr.net/npm/pdf-lib/dist/pdf-lib.min.js"; eval(UrlFetchApp.fetch(cdnjs).getContentText().replace(/setTimeout\(.*?,.*?(\d*?)\)/g, "Utilities.sleep($1);return t();")); // 合并PDF文件 const pdfDoc = await PDFLib.PDFDocument.create(); for (const data of pdfDatas) { const pdfData = await PDFLib.PDFDocument.load(data); const pages = await pdfDoc.copyPages(pdfData, pdfData.getPageIndices()); pages.forEach(page => pdfDoc.addPage(page)); } // 生成并保存合并后的PDF const bytes = await pdfDoc.save(); const blob = Utilities.newBlob(Array.from(bytes), MimeType.PDF, "merged_sample.pdf"); const mergedFile = DriveApp.createFile(blob); mergedFile.moveTo(destinationFolder); }
核心修改说明
- URL正则优化:更新正则表达式,同时匹配Google Docs和Drive文件的URL格式,确保所有有效文件ID都能被提取。
- 新增Google Docs处理:添加对Google Docs类型的判断,使用
Drive.Files.export直接导出为PDF,无需创建临时文件。 - 异步逻辑优化:用
Promise.all并行处理文件转换,提升执行效率;过滤无效ID和不支持的文件类型,避免后续流程报错。 - Blob创建优化:将
pdf-lib返回的Uint8Array转换为普通数组传入Utilities.newBlob,避免数据转换异常。 - 代码可读性提升:用
switch替代多段if-else,添加日志输出方便调试。
注意事项
- 需在Google Apps Script编辑器的「资源」→「高级Google服务」中启用Drive API。
- 首次运行脚本时需完成权限授权,确保脚本可访问Drive和表格资源。
- 若合并的PDF总页数过多,可能触发GAS内存限制,可考虑分批次合并。
内容的提问来源于stack exchange,提问作者EagleEye
相关产品推荐
相关产品推荐

