无法通过其ID从Google云端硬盘下载文件

时间:2019-06-23 10:16:37

标签: python python-3.x google-drive-api

$ pip3 list | grep googl
google-api-python-client 1.7.9    
google-auth              1.6.3    
google-auth-httplib2     0.0.3    
google-auth-oauthlib     0.4.0  

我可以成功列出共享给我的文件。但是,当我尝试通过其ID下载现有文件时,出现“找不到文件”错误。如何通过文件ID下载文件?

列出文件的脚本

from __future__ import print_function
import pickle
import os.path
import io
import sys
from googleapiclient.discovery import build
from googleapiclient.http import MediaIoBaseDownload
from google_auth_oauthlib.flow import InstalledAppFlow
from google.auth.transport.requests import Request

# If modifying these scopes, delete the file token.pickle.
SCOPES = ['https://www.googleapis.com/auth/drive.metadata.readonly']
TOKEN_FILE = 'tockenRead.pickle'

def main():
    """Shows basic usage of the Drive v3 API.
    Prints the names and ids of the first 10 files the user has access to.
    """
    creds = None
    # The file token.pickle stores the user's access and refresh tokens, and is
    # created automatically when the authorization flow completes for the first
    # time.
    if os.path.exists(TOKEN_FILE):
        with open(TOKEN_FILE, 'rb') as token:
            creds = pickle.load(token)
    # If there are no (valid) credentials available, let the user log in.
    if not creds or not creds.valid:
        if creds and creds.expired and creds.refresh_token:
            creds.refresh(Request())
        else:
            flow = InstalledAppFlow.from_client_secrets_file(
                'credentials.json', SCOPES)
            creds = flow.run_local_server()
        # Save the credentials for the next run
        with open(TOKEN_FILE, 'wb') as token:
            pickle.dump(creds, token)

    service = build('drive', 'v3', credentials=creds)

    # Call the Drive v3 API
    results = service.files().list(
        q="mimeType != 'application/vnd.google-apps.folder'",
        pageSize=10,
        fields="nextPageToken, files(id, name)"
    ).execute()
    items = results.get('files', [])

    if not items:
        print('No files found.')
    else:
        print('Files:')
        for item in items:
            print(u'{0} ({1})'.format(item['name'], item['id']))

if __name__ == '__main__':
    main()

结果

$ python3 list_files.py 
Files:
20140810_125633.mp4 (1SwYm5Z1zPczZnDulmsbA9wrEJ-JT-hwE)
Getting started (0B3K2QXOGSOFRc3RhcnRlcl9maWxl)

用于下载ID为1SwYm5Z1zPczZnDulmsbA9wrEJ-JT-hwE的文件的脚本

from __future__ import print_function
import pickle
import os.path
import io
import sys
from googleapiclient.discovery import build
from googleapiclient.http import MediaIoBaseDownload
from google_auth_oauthlib.flow import InstalledAppFlow
from google.auth.transport.requests import Request

# If modifying these scopes, delete the file token.pickle.
SCOPES = ['https://www.googleapis.com/auth/drive.file']
TOKEN_FILE = 'tokenWrite.pickle';

def downloadFile(driveService, fileId):
    request = driveService.files().get_media(fileId=fileId)
    fh = io.BytesIO()
    downloader = MediaIoBaseDownload(fh, request)
    done = False
    while done is False:
        status, done = downloader.next_chunk()
        print ("Download %d%%." % int(status.progress() * 100))

def main():
    """Shows basic usage of the Drive v3 API.
    Prints the names and ids of the first 10 files the user has access to.
    """
    creds = None
    # The file token.pickle stores the user's access and refresh tokens, and is
    # created automatically when the authorization flow completes for the first
    # time.
    if os.path.exists(TOKEN_FILE):
        with open(TOKEN_FILE, 'rb') as token:
            creds = pickle.load(token)
    # If there are no (valid) credentials available, let the user log in.
    if not creds or not creds.valid:
        if creds and creds.expired and creds.refresh_token:
            creds.refresh(Request())
        else:
            flow = InstalledAppFlow.from_client_secrets_file(
                'credentials.json', SCOPES)
            creds = flow.run_local_server()
        # Save the credentials for the next run
        with open(TOKEN_FILE, 'wb') as token:
            pickle.dump(creds, token)

    service = build('drive', 'v3', credentials=creds)

    downloadFile(service, '1SwYm5Z1zPczZnDulmsbA9wrEJ-JT-hwE')

if __name__ == '__main__':
    main()

错误

$ python3 download_files.py 
Please visit this URL to authorize this application: https://accounts.google.com/o/oauth2/auth?response_type=code&client_id=619229308650-91gkhdgo7v0jbt6df1phahmq868eb7gd.apps.googleusercontent.com&redirect_uri=http%3A%2F%2Flocalhost%3A8080%2F&scope=https%3A%2F%2Fwww.googleapis.com%2Fauth%2Fdrive.file&state=4mP9kgVJQD4ETOu5JjIRQFBLcyViAG&access_type=offline&code_challenge=ybCzMgZ2SOXdrpZZYn1dq9nSJk8wMtLo7Deg_Xix9So&code_challenge_method=S256
Traceback (most recent call last):
  File "download_files.py", line 52, in <module>
    main()
  File "download_files.py", line 49, in main
    downloadFile(service, '1SwYm5Z1zPczZnDulmsbA9wrEJ-JT-hwE')
  File "download_files.py", line 21, in downloadFile
    status, done = downloader.next_chunk()
  File "/usr/local/lib/python3.7/site-packages/googleapiclient/_helpers.py", line 130, in positional_wrapper
    return wrapped(*args, **kwargs)
  File "/usr/local/lib/python3.7/site-packages/googleapiclient/http.py", line 705, in next_chunk
    raise HttpError(resp, content, uri=self._uri)
googleapiclient.errors.HttpError: <HttpError 404 when requesting https://www.googleapis.com/drive/v3/files/1SwYm5Z1zPczZnDulmsbA9wrEJ-JT-hwE?alt=media returned "File not found: 1SwYm5Z1zPczZnDulmsbA9wrEJ-JT-hwE.">

1 个答案:

答案 0 :(得分:2)

这个答案怎么样?

问题原因:

当我看到您的脚本时,我注意到下面的脚本的范围不同于上面的脚本。我认为这是您遇到问题的原因。

在上述脚本中,使用https://www.googleapis.com/auth/drive.metadata.readonly。另一方面,在下面的脚本中,使用https://www.googleapis.com/auth/drive.file

The official document关于https://www.googleapis.com/auth/drive.file的范围如下。

  

查看和管理您使用此应用打开或创建的Google云端硬盘文件和文件夹

这意味着当脚本使用https://www.googleapis.com/auth/drive.file范围上传文件时,可以使用该范围来检索文件。但是例如,当手动将文件上传到Google云端硬盘时,即使与您共享文件,https://www.googleapis.com/auth/drive.file也无法下载该文件。

为了下载文件,以下解决方法如何?

解决方法1:

您使用https://www.googleapis.com/auth/drivehttps://www.googleapis.com/auth/drive.readonly的范围而不是https://www.googleapis.com/auth/drive.file

解决方法2:

如果需要使用https://www.googleapis.com/auth/drive.file的范围,它将使用https://www.googleapis.com/auth/drive.file的范围上载文件。这样,可以通过示波器下载文件。

注意:

  • 更改范围时,请删除文件tokenWrite.pickle,然后再次授权范围并创建新的tokenWrite.pickle。这样,您可以使用新的作用域。请注意这一点。

参考:

如果我误解了您的问题,而这不是您想要的方向,我深表歉意。

相关问题