【问题标题】:google service account credentials not working谷歌服务帐户凭据不起作用
【发布时间】:2020-08-23 10:16:41
【问题描述】:

我正在尝试创建一个简单的网络应用程序,它可以自动将我的数据库和媒体备份上传到指定的谷歌驱动器。我按照官方文档创建了一个服务帐户凭据,赋予它所有者角色,并从谷歌云平台提取了一个密钥(json文件)。我在我的帐户上启用了 Google Drive API 并编写了此代码,但 credentials.valid 返回 False,我的文件不会上传到我的驱动器。

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'))

【问题讨论】:

  • print(credentials) 说什么?
  • @yedpodtrzitko print(credentials.valid) 返回 False
  • 这太棒了,但print(credentials) 怎么说?
  • 类似这样的

标签: python google-api google-drive-api google-oauth google-api-python-client


【解决方案1】:

这个修改怎么样?

修改点:

  • 我认为在你的脚本中,serviceservice = build('drive', 'v3', credentials=credentials) 可以用于上传文件。
    • 在我的环境中,我可以确认可以使用您的脚本上传文件。
    • 来自my file would not upload to my drive.,我认为您可能对服务帐户有误解。使用服务帐户上传的文件将创建到服务帐户的 Drive。此云端硬盘不同于您帐户的 Google 云端硬盘。我想这可能是my file would not upload to my drive.的原因。
    • 如果您想在您的 Google Drive 中查看使用服务帐户上传的文件,则需要与您的 Google 帐户共享上传的文件。或者,需要将文件上传到您的 Google 云端硬盘中与服务帐户共享的文件夹中。
  • 此外,在您的脚本中,使用了file_back.get('WebContentLink')。在这种情况下,总是返回None,因为WebContentLink 必须是WebContentLink。此外,在 Drive API v3 中,默认返回值不包括 webContentLink。所以需要设置fields

当以上几点反映到您的脚本中时,您的脚本如下。

修改脚本:

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'))
  • 当您运行上述脚本时,您可以在 Google 云端硬盘的“与我共享”中看到上传的文件。

  • 如果您想放置您的 Google 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)
    
      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'))
    

注意:

  • 在当前阶段,当使用服务帐户上传的文件的所有者发生变化时,出现You can't yet change the owner of this item. (We're working on it.)之类的错误。所以我提出了上面修改的脚本。

参考资料:

【讨论】:

  • 非常感谢。我能够看到上传的文件。如何直接访问服务帐户驱动器?另外,为什么credentials.valid 返回 False?
  • @Hesam Korki 感谢您的回复。关于你的 2 个新问题,A1。现阶段无法通过浏览器直接访问服务账号的Drive。不幸的是,这是当前的规范。所以我提出了上面的修改。我为此道歉。 A2。我认为service_account.Credentials.from_service_account_file() 检索到的值不包括访问令牌。这可能是它的原因。但我不确定这是否是正确的答案。这是因为我的技术不好。我对此深表歉意。我必须多学习才能理解各种情况。
猜你喜欢
  • 2020-06-28
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2019-05-23
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多