问题描述
我正在尝试使用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密钥。
- 使用API密钥和要下载的文件ID向Web Apps请求。
- 在Web Apps上,运行以下功能。
- 已接收文件ID的文件许可被更改。文件开始公开共享。
- 安装时间驱动的触发器。在这种情况下,触发器将在1分钟后运行。
- 当该函数由时间驱动的触发器运行时,文件的权限会更改。并且共享文件停止。这样,可以实现只有一分钟的共享文件。
- Web Apps返回用于下载文件ID的文件的端点。
- 获取端点后,请在1分钟内使用端点下载文件。因为文件仅共享了一分钟。
用法:
1。创建一个独立的脚本
在这种解决方法中,Google Apps脚本用作服务器端。请创建一个独立的脚本。 如果您想直接创建它,请访问https://script.new/。在这种情况下,如果您尚未登录Google,则会打开“登录”屏幕。因此,请登录到Google。这样,将打开Google 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应用
- 在脚本编辑器上,通过“发布”->“作为Web应用程序部署”打开一个对话框。
- 在“将应用程序执行为:”中选择“我”。
- 在“谁有权访问该应用程序:”中选择“所有人,甚至匿名”。这是一个测试案例。
- 如果使用了“只有我自己”,则只有您可以访问Web Apps。那时,请使用您的访问令牌。
- 单击“部署”按钮作为新的“项目版本”。
- 自动打开“需要授权”对话框。
- 点击“查看权限”。
- 选择自己的帐户。
- 在“此应用未验证”中单击“高级”。
- 点击“转到###项目名称###(不安全)”
- 单击“允许”按钮。
- 点击“确定”
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应用程序中。请注意这一点。