0

I am trying to create a simple web application that automatically uploads my database & media backup to a designated google drive. I have followed the official document and created a service account credential, gave it the owner role, and extracted a key(json file) from Google cloud platform. I enabled the Google Drive API on my account and wrote this code, but the credentials.valid returns False and my file would not upload to my drive.

from google.oauth2 import service_account
import googleapiclient as google
from googleapiclient.http import MediaFileUpload, HttpRequest
from googleapiclient.discovery import build

SCOPES = ['https://www.googleapis.com/auth/drive']

credentials = service_account.Credentials.from_service_account_file('./service-credentials.json', scopes=SCOPES)

print(credentials.valid)

service = build('drive', 'v3', credentials=credentials)
file_metadata = {'name' : 'python.png'}
media = MediaFileUpload('./python.png', mimetype='image/png')
file_up = service.files().create(body=file_metadata, media_body=media, fields='id').execute()

file_back = service.files().get(fileId=file_up['id']).execute()

print(file_back.get('WebContentLink'))

4
  • what does print(credentials) say? Commented Aug 23, 2020 at 10:31
  • @yedpodtrzitko the print(credentials.valid) returns False Commented Aug 23, 2020 at 11:30
  • that's awesome, but what does print(credentials) say? Commented Aug 23, 2020 at 15:21
  • <Object Credential at 8263839> something like this Commented Aug 23, 2020 at 18:27

1 Answer 1

5

How about this modification?

Modification points:

  • I think that in your script, service of service = build('drive', 'v3', credentials=credentials) can be used for uploading the file.
    • In my environment, I could confirm that the file can be uploaded using your script.
    • From my file would not upload to my drive., I thought that you might misunderstand about the service account. The file uploaded with the service account is created to the Drive of the service account. This Drive is different from your Google Drive of your account. I thought that this might be the reason of my file would not upload to my drive..
    • If you want to see the file uploaded with the service account at your Google Drive, it is required to share the uploaded file with your Google account. Or, it is required to upload the file to the folder in your Google Drive shared with the service account.
  • And also, in your script, file_back.get('WebContentLink') is used. In this case, None is always returned because WebContentLink is required to be WebContentLink. And also, in Drive API v3, the default returned values don't include webContentLink. So it is required to set fields.

When above points are reflected to your script, your script becomes as follows.

Modified script:

from google.oauth2 import service_account
import googleapiclient as google
from googleapiclient.http import MediaFileUpload, HttpRequest
from googleapiclient.discovery import build

SCOPES = ['https://www.googleapis.com/auth/drive']
credentials = service_account.Credentials.from_service_account_file('./service-credentials.json', scopes=SCOPES)

service = build('drive', 'v3', credentials=credentials)
file_metadata = {'name': 'python.png'}
media = MediaFileUpload('./python.png', mimetype='image/png')
file_up = service.files().create(body=file_metadata, media_body=media, fields='id').execute()

# Create a permission. Here, your Google account is shared with the uploaded file.
yourEmailOfGoogleAccount = '###'  # <--- Please set your Email address of Google account.
permission = {
    'type': 'user',
    'role': 'writer',
    'emailAddress': yourEmailOfGoogleAccount,
}
service.permissions().create(fileId=file_up['id'], body=permission).execute()

file_back = service.files().get(fileId=file_up['id'], fields='webContentLink').execute()  # or fields='*'
print(file_back.get('webContentLink'))
  • When you run above script, the uploaded file can be seen at "Shared with me" in your Google Drive.

  • If you want to put the specific folder of your Google Drive, please use the following script. In this case, before you run the script, please share the folder with the email of the service account. Please be careful this.

      from google.oauth2 import service_account
      import googleapiclient as google
      from googleapiclient.http import MediaFileUpload, HttpRequest
      from googleapiclient.discovery import build
    
      SCOPES = ['https://www.googleapis.com/auth/drive']
      credentials = service_account.Credentials.from_service_account_file('./service-credentials.json', scopes=SCOPES)
    
      service = build('drive', 'v3', credentials=credentials)
      file_metadata = {'name': 'python.png', 'parents': ['###']}  # <--- Please set the folder ID shared with the service account.
      media = MediaFileUpload('./python.png', mimetype='image/png')
      file_up = service.files().create(body=file_metadata, media_body=media, fields='id').execute()
    
      file_back = service.files().get(fileId=file_up['id'], fields='webContentLink').execute()  # or fields='*'
      print(file_back.get('webContentLink'))
    

Note:

  • In the current stage, when the owner of file uploaded with the service account is changed, an error like You can't yet change the owner of this item. (We're working on it.). So I proposed above modified script.

References:

Sign up to request clarification or add additional context in comments.

2 Comments

Thank you so much. I was able to see the uploaded file. How may I access the service account drive directly? Also, why do the credentials.valid returns False?
@Hesam Korki Thank you for replying. About your 2 new questions, A1. In the current stage, it cannot directly access to Drive of service account using browser. Unfortunately, this is the current specification. So I proposed above modification. I apologize for this. A2. I think that the value retrieved by service_account.Credentials.from_service_account_file() doesn't include the access token. This might be the reason of it. But I'm not sure whether this is the correct answer. This is due to my poor skill. I deeply apologize for this. I have to study more for understanding various situations.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.