我正在尝试使用Google云端硬盘API获取文件的直接下载链接 修改点:修改后的脚本:注意:参考: 1创建一个独立的脚本 2设置服务器端示例脚本 3部署Web应用 4试运行:客户端

问题描述

我正在尝试使用Google Drive API(v3)获取Google Drive中文件的直接下载链接,但是我也试图在不公开共享文件的情况下执行此操作。 这是我尝试过的:

https://www.googleapis.com/drive/v3/files/**FILE_ID**?alt=media&supportsAllDrives=True&includeItemsFromAllDrives=True&key=**API_KEY**

现在,如果文件是公共共享的,则可以使用。但是,当文件未公开共享时,您会收到以下消息:

{'error': {'errors': [{'domain': 'global','reason': 'notFound','message': 'File not found: 10k0Qogwcz7k0u86m7W2HK-LO7bk8xAF8.','locationType': 'parameter','location': 'fileId'}],'code': 404,'message': 'File not found: 10kfdsfjDHJ38-UHJ34D82.'}}

在进行一些谷歌搜索之后,我发现了一个堆栈溢出的帖子,说我需要使用访问令牌添加一个请求标头,但这不起作用,应用程序只是挂起

这是完整的代码:

### SETTING UP GOOGLE API
scopes = 'https://www.googleapis.com/auth/drive'
store = file.Storage('storage.json')
credentials = store.get()
if not credentials or credentials.invalid:
    flow = client.flow_from_clientsecrets('client_secret.json',scopes)
    credentials = tools.run_flow(flow,store)
accessToken = credentials.access_token
refreshToken = credentials.refresh_token
drive = build('drive','v3',credentials=credentials)


### SENDING REQUEST
    req_url = "https://www.googleapis.com/drive/v3/files/"+file_id+"?alt=media&supportsAllDrives=True&includeItemsFromAllDrives=True&key="+GOOGLE_API_KEY
    headers={'Authorization': 'Bearer %s' % accessToken}
    request_content = json.loads((requests.get(req_url)).content)
    print(request_content)

------------------ 编辑: ------------------ >

我已经很接近答案了,但是我似乎无法弄清为什么它不起作用。

因此,我之前已经弄清楚alt=media会为该文件生成一个下载链接,但是当该文件为私有文件时,它将无法正常工作。

我刚刚发现您可以添加&access_token=....来访问私有文件,所以我想到了这个API调用:

https://www.googleapis.com/drive/v3/files/**FILE_ID**?supportsAllDrives=true&alt=media&access_token=**ACCESS_TOKEN**&key=**API_KEY**

当我在浏览器中转到该URL时,会收到以下消息:

We're sorry...
... but your computer or network may be sending automated queries. To protect our users,we can't process your request right now.

我觉得这很混乱,因为如果删除alt=media,就可以调用该请求,并且可以获得有关该文件的一些元数据。

解决方法

我相信您的目标如下。

  • 我知道从I'm trying to get the direct download link for a file in Google Drive using the Google Drive API (v3),中检索webContentLink
  • 您要检索的webContentLink文件是Google Docs文件之外的文件。
  • 您已经能够使用Drive API获取文件元数据。因此,您的访问令牌可以用于此目的。

修改点:

  • 不共享文件时,无法使用API​​密钥。这样,https://www.googleapis.com/drive/v3/files/**FILE_ID**?alt=media&supportsAllDrives=True&includeItemsFromAllDrives=True&key=**API_KEY**返回File not found。我认为这个问题的原因是由于这个原因。
  • 当我在问题中看到您的脚本时,似乎您想下载文件内容。
  • 在您的脚本中,未使用headers。因此,在这种情况下,不使用访问令牌。
  • 在“文件:获取”方法中,没有includeItemsFromAllDrives
  • 在您的脚本中,我认为credentials.access_token处发生错误。这个怎么样?如果我的理解正确,请尝试将其修改为accessToken = credentials.token
  • 在Drive API v3中,默认响应值不包含webContentLink。因此,在这种情况下,必须将字段值设置为fields=webContentLink

修改脚本后,它如下所示。

修改后的脚本:

file_id = '###'  # Please set the file ID.
req_url = "https://www.googleapis.com/drive/v3/files/" + file_id + "?supportsAllDrives=true&fields=webContentLink"
headers = {'Authorization': 'Bearer %s' % accessToken}
res = requests.get(req_url,headers=headers)
obj = res.json()
print(obj.get('webContentLink'))

或者,您可以在脚本中使用drive = build('drive','v3',credentials=credentials),也可以使用以下脚本。

file_id = '###'  # Please set the file ID.
drive = build('drive',credentials=credentials)
request = drive.files().get(fileId=file_id,supportsAllDrives=True,fields='webContentLink').execute()
print(request.get('webContentLink'))

注意:

  • 在此修改后的脚本中,
    • 如果文件位于共享驱动器中,并且您没有检索文件元数据的权限,则会发生错误。
    • 当您的访问令牌无法用于检索文件元数据时,会发生错误。

所以请注意以上几点。

  • *用作fields时,可以检索所有文件元数据。

参考:

已添加:

  • 您要通过URL从Google云端硬盘下载二进制数据。
  • 文件大小很大,例如“ 2-10 GB”。

在这种情况下,不幸的是,无法使用webContentLink。因为在这种大文件的情况下,webContentLink被重定向。因此,我认为公开共享文件并使用API​​密钥的方法适合实现您的目标。但是,您不能公开共享文件。

在这种情况下,作为一种解决方法,我建议使用this method。此方法是“一次性下载Google云端硬盘”。在Google云端硬盘中,下载了公共共享文件后,即使在下载过程中删除了文件许可权,也可以运行下载。此方法使用此方法。

流量

在此示例脚本中,使用了API密钥。

  1. 使用API​​密钥和要下载的文件ID向Web Apps请求。
  2. 在Web Apps上,运行以下功能。
    • 已接收文件ID的文件许可被更改。文件开始公开共享。
    • 安装时间驱动的触发器。在这种情况下,触发器将在1分钟后运行。
      • 当该函数由时间驱动的触发器运行时,文件的权限会更改。并且共享文件停止。这样,可以实现只有一分钟的共享文件。
  3. Web Apps返回用于下载文件ID的文件的端点。
    • 获取端点后,请在1分钟内使用端点下载文件。因为文件仅共享了一分钟。

用法:

1。创建一个独立的脚本

在这种解决方法中,Google Apps脚本用作服务器端。请创建一个独立的脚本。 如果您想直接创建它,请访问https://script.new/。在这种情况下,如果您尚未登录Google,则会打开“登录”屏幕。因此,请登录到Google。这样,将打开Goog​​le Apps脚本的脚本编辑器。

2。设置服务器端示例脚本

请复制以下脚本并将其粘贴到脚本编辑器中。那时,请在函数key中将API密钥设置为doGet(e)的变量。

在这里,请在doGet(e)函数中设置您的API密钥。在此Web Apps中,如果输入的API密钥相同,则脚本将运行。

function deletePermission() {
  const forTrigger = "deletePermission";
  const id = CacheService.getScriptCache().get("id");
  const triggers = ScriptApp.getProjectTriggers();
  triggers.forEach(function(e) {
    if (e.getHandlerFunction() == forTrigger) ScriptApp.deleteTrigger(e);
  });
  const file = DriveApp.getFileById(id);
  file.setSharing(DriveApp.Access.PRIVATE,DriveApp.Permission.NONE);
}

function checkTrigger(forTrigger) {
  const triggers = ScriptApp.getProjectTriggers();
  for (var i = 0; i < triggers.length; i++) {
    if (triggers[i].getHandlerFunction() == forTrigger) {
      return false;
    }
  }
  return true;
}

function doGet(e) {
  const key = "###"; // <--- API key. This is also used for checking the user.
  
  const forTrigger = "deletePermission";
  var res = "";
  if (checkTrigger(forTrigger)) {
    if ("id" in e.parameter && e.parameter.key == key) {
      const id = e.parameter.id;
      CacheService.getScriptCache().put("id",id,180);
      const file = DriveApp.getFileById(id);
      file.setSharing(DriveApp.Access.ANYONE_WITH_LINK,DriveApp.Permission.VIEW);
      var d = new Date();
      d.setMinutes(d.getMinutes() + 1);
      ScriptApp.newTrigger(forTrigger).timeBased().at(d).create();
      res = "https://www.googleapis.com/drive/v3/files/" + id + "?alt=media&key=" + e.parameter.key;
    } else {
      res = "unavailable";
    }
  } else {
    res = "unavailable";
  }
  return ContentService.createTextOutput(res);
}

3。部署Web应用

  1. 在脚本编辑器上,通过“发布”->“作为Web应用程序部署”打开一个对话框。
  2. 在“将应用程序执行为:”中选择“我”。
  3. 在“谁有权访问该应用程序:”中选择“所有人,甚至匿名”。这是一个测试案例。
    • 如果使用了“只有我自己”,则只有您可以访问Web Apps。那时,请使用您的访问令牌。
  4. 单击“部署”按钮作为新的“项目版本”。
  5. 自动打开“需要授权”对话框。
    1. 点击“查看权限”。
    2. 选择自己的帐户。
    3. 在“此应用未验证”中单击“高级”。
    4. 点击“转到###项目名称###(不安全)”
    5. 单击“允许”按钮。
  6. 点击“确定”

4。试运行:客户端

这是python的示例脚本。在测试之前,请确认以上脚本已部署为Web Apps。并且请设置Web Apps的URL,文件ID和您的API密钥。

import requests
url1 = "https://script.google.com/macros/s/###/exec"
url1 += "?id=###fileId###&key=###your API key###"
res1 = requests.get(url1)
url2 = res1.text
res2 = requests.get(url2)
with open("###sampleFilename###","wb") as f:
    f.write(res2.content)
  • 在此示例脚本中,首先,它使用文件ID和API密钥向Web Apps请求,并在1分钟内公开共享该文件。然后,可以下载文件。 1分钟后,该文件未公开共享。但是文件的下载可以保留。

注意:

  • 修改Web应用程序的脚本后,请重新部署Web应用程序为新版本。这样,最新的脚本就会反映到Web应用程序中。请注意这一点。

参考文献:

相关问答

依赖报错 idea导入项目后依赖报错,解决方案:https://blog....
错误1:代码生成器依赖和mybatis依赖冲突 启动项目时报错如下...
错误1:gradle项目控制台输出为乱码 # 解决方案:https://bl...
错误还原:在查询的过程中,传入的workType为0时,该条件不起...
报错如下,gcc版本太低 ^ server.c:5346:31: 错误:‘struct...