问题
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'))
回答1:
How about this modification?
Modification points:
- I think that in your script,
service
ofservice = 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 ofmy 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 becauseWebContentLink
is required to beWebContentLink
. And also, in Drive API v3, the default returned values don't includewebContentLink
. So it is required to setfields
.
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:
- Files: create
- Files: get
- Permissions: create
来源:https://stackoverflow.com/questions/63545788/google-service-account-credentials-not-working