pythongoogle-apigoogle-drive-apigoogle-api-python-clientshared-drive

How to move a file in a shared google drive to trash using a service account


I use a service account that is content-manager. I have no problem uploading files to the shared drive using the drive-api from python. Using

service.files().list(q="name='file_name'", fields="files(id)").execute() 

I obtain the file_id from my code. This file_id is the right one based on the link to the file.

When I perform the following statement:

response = service.files().update(fileId=file_id, body={'trashed': True}).execute()

I get a

404: file not found.

How to resolve this ? With my personal account (also as content-manager) I have no problems trashing the file.


Solution

  • Requirements

    If you clearly understand how to impersonate an account you can skip to the Solution step.

    Solution

    By default Python Google Drive API client V3 doesn't include shared drive files, that's why you have to explicitly pass a parameter supportsAllDrives and set it to True and before that you should list your files in order to know the fileId parameter by using includeItemsFromAllDrives and supportsAllDrives. Here's an example to list all the files in all your drives and how to trash a file in a Shared Drive using a service account:

    from googleapiclient.discovery import build
    from google.oauth2 import service_account
    
    SCOPES = ['https://www.googleapis.com/auth/drive']
    SERVICE_ACCOUNT_FILE = './service_account_key.json'
    
    credentials = service_account.Credentials.from_service_account_file(SERVICE_ACCOUNT_FILE, scopes=SCOPES)
    
    # Impersonate user@example.com account in my example.com domain
    delegated_credentials = credentials.with_subject('user@example.com')
    
    # Use the delegated credentials to impersonate the user
    service = build('drive', 'v3', credentials=delegated_credentials)
    
    # List all the files in your Drives (Shared Drives included)
    results = service.files().list(fields="nextPageToken, files(id, name, trashed)", includeItemsFromAllDrives=True, supportsAllDrives=True).execute()
    items = results.get('files', [])
    
    if not items:
        print('No files found.')
    else:
        print('Files:')
        for item in items:
            print(u'{0} ({1}) - Trashed? {2}'.format(item['name'], item['id'], item['trashed']))
    
    # Use the filedId in order to trash your shared file
    response = service.files().update(fileId=fileId, body={'trashed': True}, supportsAllDrives=True).execute()
    print(response)
    

    Otherwise if you already know the fileId just use the update part.

    Reference

    Python Google Drive API client V3 > Update a file

    Google Identity Platform > Impersonate a user by using a service account