Search code examples
pythongoogle-apigoogle-drive-apigoogle-drive-shared-drive

Can list files but can't download from shared drive when using Google Drive Python API


I'm trying to write some code to download a file from a shared Google drive using a service account; the current version of my code is shared below. The code and service account works for me when using on a user drive, but I get HttpError 404 when the fileID belongs to a shared drive. The service account has been already given access to the shared drive. I'm in fact able to list the files on the shared drive folder, but download doesn't work for some reason. Can you please help me figure out what I'm doing wrong?

import io

from google.oauth2 import service_account
from googleapiclient.discovery import build
from googleapiclient.http import MediaIoBaseDownload

_CREDENTIALS_FILE = "path_to_credentials.json"

scopes = [
    "https://www.googleapis.com/auth/drive.readonly",
    "https://www.googleapis.com/auth/drive.file",
    "https://www.googleapis.com/auth/drive",
]

# Load service account credentials
creds = service_account.Credentials.from_service_account_file(
    _CREDENTIALS_FILE, scopes=scopes
)

# Create the Google Drive API service
service = build("drive", "v3", credentials=creds)


save_name = "test_file_delete.me"

fileID = "SOME_FILE_ID"  # works with a user drive but not with a shared drive
file = service.files().get(fileId=fileID).execute()

request = service.files().get_media(fileId=file["id"])
fh = io.FileIO(save_name, "wb")
downloader = MediaIoBaseDownload(fh, request)
done = False
while not done:
    _, done = downloader.next_chunk()

Solution

  • How about modifying as follows?

    From:

    file = service.files().get(fileId=fileID).execute()
    
    request = service.files().get_media(fileId=file["id"])
    

    To:

    file = service.files().get(fileId=fileID, supportsAllDrives=True).execute()
    request = service.files().get_media(fileId=file["id"], supportsAllDrives=True)
    

    or, I think that in your script, when you want to download a file of fileID, the following modification might be able to be also used. By this, the number of Drive API can be reduced by one.

    request = service.files().get_media(fileId=fileID, supportsAllDrives=True)
    

    Reference: