You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何在不使用受限OAuth权限的情况下下载Google Drive文件?

Google Drive Picker API 文件下载401权限问题

场景说明

我正在开发Google Drive集成功能,流程为:前端通过Google Picker API让用户选择文件,将文件信息传递至后端,后端完成文件下载后上传至S3。为规避https://www.googleapis.com/auth/drive和https://www.googleapis.com/auth/drive.readonly这类受限权限,我通过Picker API获取文件的downloadUrl用于下载操作。

前端Picker代码

const pickerCallback = async (data) => {
  if (data.action === window.google.picker.Action.PICKED) {
    const files = data.docs.map((doc) => ({
      id: doc.id,
      name: doc.name,
      mimeType: doc.mimeType,
      size: doc.sizeBytes,
      downloadUrl: doc.url,
    }));

    console.log("Files selected:", files);
    // Send file details to the backend for downloading
  }
};

后端下载代码

async function downloadFileUsingUrl(downloadUrl: string, accessToken: string): Promise<NodeJS.ReadableStream> {
  const response = await fetch(downloadUrl, {
    headers: {
      Authorization: `Bearer ${accessToken}`,
    },
  });

  console.log(`Download API response status: ${response.status} ${response.statusText}`);

  if (!response.ok) {
    console.error(`Download API error response: ${await response.text()}`);
    throw new Error(`Failed to download file: ${response.statusText}`);
  }

  return response.body as unknown as NodeJS.ReadableStream;
}

遇到的错误

Download API response status: 401 Unauthorized
Download API error response: ...
Failed to download file: Unauthorized

已尝试的操作

  • 使用Google Picker提供的downloadUrl
  • 确认access token有效且可用于其他请求
  • 调整请求头模拟浏览器请求(添加Referer、User-Agent),仍返回401
  • 考虑过替代API,但安全评估要求必须避免受限权限

问题

  1. 如何在不使用https://www.googleapis.com/auth/drive这类受限权限的情况下,通过Picker API下载文件?
  2. 是否有其他方式处理该流程而不触发受限权限要求?

解决方案

问题根源

Picker API返回的doc.url是面向前端浏览器的下载链接,不支持后端通过Authorization头携带token调用——这类链接依赖浏览器环境的用户会话(如用户已登录Google账号的Cookie),后端服务器环境无法复用该会话,因此即使携带token也会返回401。

Picker API的文件对象包含exportLinks(针对Google原生文档,如Docs/Sheets)和webContentLink(针对普通文件)字段,这两个链接支持通过Authorization头携带token调用,且仅需要https://www.googleapis.com/auth/drive.file权限(该权限属于非受限的"敏感权限",审核流程更简单)。

修改前端代码获取正确的下载链接:

const pickerCallback = async (data) => {
  if (data.action === window.google.picker.Action.PICKED) {
    const files = data.docs.map((doc) => {
      let downloadUrl;
      // 区分Google原生文档和普通文件
      if (doc.mimeType.startsWith('application/vnd.google-apps')) {
        // 原生文档用exportLinks,选择对应导出格式(示例为PDF)
        downloadUrl = doc.exportLinks['application/pdf'];
        // 可根据文档类型调整格式:如Spreadsheet选text/csv,Document选docx格式
      } else {
        // 普通文件用webContentLink
        downloadUrl = doc.webContentLink;
      }
      return ({
        id: doc.id,
        name: doc.name,
        mimeType: doc.mimeType,
        size: doc.sizeBytes,
        downloadUrl: downloadUrl,
      });
    });

    console.log("Files selected:", files);
    // Send file details to the backend for downloading
  }
};

后端代码无需修改,确保token包含https://www.googleapis.com/auth/drive.file权限即可。

方案2:前端直接下载后传给后端

若不想调整权限,可让前端直接通过Picker返回的链接下载文件(前端处于浏览器环境,具备用户的Google会话),再将文件Blob/FormData传递给后端,由后端上传至S3。此方式无需后端调用Drive API,完全规避受限权限问题。

示例前端代码:

const pickerCallback = async (data) => {
  if (data.action === window.google.picker.Action.PICKED) {
    const files = await Promise.all(data.docs.map(async (doc) => {
      // 前端直接下载文件
      const response = await fetch(doc.url);
      const blob = await response.blob();
      // 转换为File对象方便上传
      const file = new File([blob], doc.name, { type: doc.mimeType });
      return {
        file,
        name: doc.name,
        mimeType: doc.mimeType,
      };
    }));

    // 用FormData传递文件到后端
    const formData = new FormData();
    files.forEach((item) => formData.append('files', item.file, item.name));
    
    await fetch('/api/upload-to-s3', {
      method: 'POST',
      body: formData,
    });
  }
};

后端只需接收FormData,直接上传至S3即可,无需处理Drive权限相关逻辑。

补充说明

  • drive.file权限仅允许应用访问用户通过Picker或应用本身打开/创建的文件,符合最小权限原则,审核难度远低于受限权限。
  • 前端直接下载的方式需注意文件大小限制:若用户选择大文件,前端下载后再上传会占用较多浏览器资源,需根据业务场景评估可行性。

内容的提问来源于stack exchange,提问作者Andrew

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.16 04:17:25