使用drive.file scope时,Google Apps Script前端调用Drive API失败
drive.file scope时Google Drive API调用返回"File not found" 我正在用Google Apps Script开发Google Sheets插件,需求是让用户通过Google File Picker选择文件后,由后端对文件执行操作。为了缩短插件审核时间(从2个月到数天)并提升安全性,我尝试用更严格的drive.file scope替代drive scope,但遇到了问题:按照scope定义,应用应该能访问用户主动选择的文件,但调用await gapi.client.drive.files.get(...)时始终返回"File not found",且文件缩略图只显示灰白方块。
解决方案
1. 理解drive.file scope的权限逻辑
drive.file scope仅允许访问用户通过当前应用主动选择/授权的文件,但前端直接调用gapi.client.drive.files.get时,OAuth令牌的权限关联存在上下文差异,导致无法正确识别文件权限。正确的做法是将选中的文件ID传递到后端(Apps Script环境)处理。
2. 修改前端回调,传递文件ID到后端
修改chooseFilesDialog.html中的pickerCallback函数,不再直接调用Drive API,而是把选中的文件ID列表传给后端函数:
async function pickerCallback(data) { var action = data[google.picker.Response.ACTION]; if (action == google.picker.Action.PICKED) { var docs = data[google.picker.Response.DOCUMENTS]; // 提取所有选中文件的ID var fileIds = docs.map(doc => doc[google.picker.Document.ID]); // 调用后端处理函数 google.script.run.withSuccessHandler(handleFileData) .processSelectedFiles(fileIds); } } // 处理后端返回的文件数据 function handleFileData(fileDataList) { console.log("获取到的文件数据:", fileDataList); // 可在此更新UI,比如显示文件信息或缩略图 }
3. 后端实现文件处理逻辑
在Main.gs中添加processSelectedFiles函数,使用Apps Script内置的DriveApp或高级Drive API访问文件,这样能正确利用drive.file scope的权限:
function processSelectedFiles(fileIds) { var fileDataList = []; for (var i = 0; i < fileIds.length; i++) { try { var file = DriveApp.getFileById(fileIds[i]); fileDataList.push({ id: file.getId(), name: file.getName(), mimeType: file.getMimeType(), thumbnailLink: file.getThumbnail() // 获取带权限的缩略图链接 }); } catch (e) { console.error("访问文件失败:", e); fileDataList.push({ id: fileIds[i], error: "文件未找到" }); } } return fileDataList; }
4. 缩略图显示问题解决
前端直接使用Picker返回的缩略图链接会因权限问题无法显示,后端返回的file.getThumbnail()会生成带有效权限的链接,可直接用于UI展示。
额外注意事项
- 若需要更详细的文件信息,可在Apps Script编辑器中启用高级Google服务里的Drive API,使用
Drive.Files.get(fileId, {fields: "id,name,mimeType,thumbnailLink"})替代DriveApp。 - 确保Picker的
setOrigin(google.script.host.origin)设置正确,避免跨域权限问题。
内容的提问来源于stack exchange,提问作者dkvnkl

