使用Google Apps Script打开Drive PDF链接时遭遇403错误求助
解决Google Drive PDF在Apps Script对话框中加载的403错误
你遇到的403错误是因为Google Drive的直接文件链接在iframe环境下会触发跨域权限限制——哪怕你能直接访问该链接,iframe的上下文也无法通过Drive的权限校验。以下是几种可行的解决方法:
方法1:转换为Google Docs Viewer嵌入链接
将Drive文件链接转换为Google Docs Viewer的专用嵌入格式,该格式针对iframe场景做了权限适配:
修改.gs代码中的URL处理逻辑
function printPdf() { const sheet = SpreadsheetApp.getActive().getSheets()[4]; const ui = SpreadsheetApp.getUi(); const orderId = ui.prompt('Enter an order ID', '', ui.ButtonSet.OK).getResponseText(); const orderQuery = sheet.getRange('S:S').createTextFinder(orderId).matchEntireCell(true).findNext(); if (!orderQuery) { ui.alert('Order ID not found'); return; } let url = sheet.getRange(orderQuery.getRow(), 15).getValue(); // 提取Drive文件ID const fileIdMatch = url.match(/d\/([a-zA-Z0-9_-]+)/); if (!fileIdMatch) { ui.alert('Invalid Drive link'); return; } const fileId = fileIdMatch[1]; // 生成Docs Viewer嵌入链接 url = `https://docs.google.com/viewer?url=https://drive.google.com/uc?id=${fileId}&embedded=true`; const template = HtmlService.createTemplateFromFile('check-out-modeless'); template.url = url; const html = template.evaluate().setWidth(800).setHeight(600); ui.showModelessDialog(html, 'Print Label'); }
注意:需确保目标PDF文件的共享权限至少设置为「有链接的人可查看」。
方法2:将PDF转为Data URI加载(最可靠)
直接通过DriveApp获取PDF文件的Blob,转为Base64编码的Data URI,完全绕过Drive的跨域限制:
修改后的.gs代码
function printPdf() { const sheet = SpreadsheetApp.getActive().getSheets()[4]; const ui = SpreadsheetApp.getUi(); const orderId = ui.prompt('Enter an order ID', '', ui.ButtonSet.OK).getResponseText(); const orderQuery = sheet.getRange('S:S').createTextFinder(orderId).matchEntireCell(true).findNext(); if (!orderQuery) { ui.alert('Order ID not found'); return; } const fileUrl = sheet.getRange(orderQuery.getRow(), 15).getValue(); const fileId = fileUrl.match(/d\/([a-zA-Z0-9_-]+)/)[1]; try { const file = DriveApp.getFileById(fileId); const blob = file.getBlob(); // 生成Data URI const dataUri = `data:${blob.getContentType()};base64,${Utilities.base64Encode(blob.getBytes())}`; const template = HtmlService.createTemplateFromFile('check-out-modeless'); template.url = dataUri; const html = template.evaluate().setWidth(800).setHeight(600); ui.showModelessDialog(html, 'Print Label'); } catch (e) { ui.alert(`Failed to load PDF: ${e.message}`); } }
对应HTML无需修改
原来的iframe可以直接加载Data URI,不会有任何权限问题。这种方法不依赖外部服务,只要当前用户有权限访问目标Drive文件即可生效。
方法3:调整打印时机(配合前两种方法使用)
原HTML中window.print()会在iframe未加载完成时执行,可能触发权限错误或打印空白。可以修改代码等待PDF渲染完成后再触发打印:
<!DOCTYPE html> <html> <head> <base target="_top"> <style> body { margin: 0; } iframe { border: none; } </style> </head> <body> <iframe id="pdfFrame" src="<?= url ?>" style="width:100%; height:100%"></iframe> <script> const frame = document.getElementById('pdfFrame'); frame.onload = function() { setTimeout(() => { window.print(); google.script.host.close(); }, 1000); // 延迟1秒确保PDF渲染完成 }; </script> </body> </html>
内容的提问来源于stack exchange,提问作者kanwoody
相关产品推荐
相关产品推荐

