Невозможно загрузить файл по его идентификатору с Google Диска - PullRequest
1 голос
/ 23 июня 2019
$ 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  

Я могу успешно перечислить файлы, к которым мне предоставлен доступ.Но я получаю сообщение об ошибке «Файл не найден» при попытке загрузить существующий файл по его идентификатору.Как скачать файл по его идентификатору?

Скрипт для вывода списка файлов

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)

Скрипт для скачивания файла с идентификатором 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 Ответ

2 голосов
/ 24 июня 2019

Как насчет этого ответа?

Причина выпуска:

Когда я увидел ваши сценарии, я заметил, что область действия приведенного ниже сценария отличается от описанного выше сценария. Я думаю, что это причина вашей проблемы.

В приведенном выше сценарии используется https://www.googleapis.com/auth/drive.metadata.readonly. С другой стороны, в приведенном ниже сценарии используется https://www.googleapis.com/auth/drive.file.

В официальном документе говорится о сфере действия 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/drive или https://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. Таким образом, вы можете использовать новые области. Пожалуйста, будьте осторожны с этим.

Справка:

Если я неправильно понял ваш вопрос, а это не то направление, которое вы хотите, я прошу прощения.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...