用于在“与我共享”上创建/更新文件的 Google API;文件夹

发布于 2025-01-13 09:41:55 字数 2093 浏览 5 评论 0 原文

我一直在尝试使用 Google API 在另一个用户与我共享的文件夹上创建文件(我确保我对其具有编辑权限)。当我将 files.create 模块与 supportsAllDrives=True 一起使用时,我收到以下错误消息:

{ "errorMessage": "<请求 https://www.googleapis.com/upload/drive/v3/files?supportsTeamDrives=true&alt=json&uploadType=multipart 返回“找不到文件:1aLcUoiiI36mbCt7ZzWoHr8RN1nIPlPg7。”。详细信息:“[ {'domain': 'global', 'reason': 'notFound', 'message': '找不到文件: 1aLcUoiiI36mbCt7ZzWoHr8RN1nIPlPg7。', 'locationType': '参数', 'location': 'fileId'}]">", "errorType": "HttpError", "requestId": "fc549b9e-9590-4ab4-8aaa-f5cea87ba4b6", “堆栈跟踪”:[ " 文件 "/var/task/lambda_function.py",第 154 行,在 lambda_handler\n upload_file(service, download_path, file_name, file_name,folder_id, 'application/vnd.openxmlformats-officedocument.spreadsheetml.sheet')\n", " 文件 "/var/task/lambda_function.py",第 78 行,在 upload_file\n file = service.files().create(\n", " 文件 "/opt/python/googleapiclient/_helpers.py",第 131 行,位于positional_wrapper\n returnwrapped(*args, **kwargs)\n", " 文件 "/opt/python/googleapiclient/http.py",第 937 行,在执行\n 时引发 HttpError(resp, content, uri=self.uri)\n" ] }

经过一番深入研究,我发现“共享云端硬盘”与“与我共享”不同,并且到目前为止我发现的所有 API 都仅适用于“共享云端硬盘” supportsTeamDrives=True 已被弃用,我无法在文档中找到相关的替换参数。 file.list api 有一个参数 sharedWithMe=True,我不确定如何在我的代码中使用它,因为 file.create 无论如何都看不到“与我共享”文件夹的文件夹ID。如有任何建议,请提前表示感谢!

我当前的代码:

def upload_file(service, file_name_with_path, file_name, description, folder_id, mime_type):  
    
media_body = MediaFileUpload(file_name_with_path, mimetype=mime_type)

body = {
    'name': file_name,
    'title': file_name,
    'description': description,
    'mimeType': mime_type,
    'parents': [folder_id]
}

file = service.files().create(
    supportsAllDrives=True,
    supportsTeamDrives=True,
    body=body,
    media_body=media_body).execute()

I have been trying to use the Google API to create files on a folder that's been shared with me by another user (I made sure I have edit permissions on it). When I was using the files.create module with supportsAllDrives=True I got the following error message:

{
"errorMessage": "<HttpError 404 when requesting https://www.googleapis.com/upload/drive/v3/files?supportsTeamDrives=true&alt=json&uploadType=multipart returned "File not found: 1aLcUoiiI36mbCt7ZzWoHr8RN1nIPlPg7.". Details: "[{'domain': 'global', 'reason': 'notFound', 'message': 'File not found: 1aLcUoiiI36mbCt7ZzWoHr8RN1nIPlPg7.', 'locationType': 'parameter', 'location': 'fileId'}]">",
"errorType": "HttpError",
"requestId": "fc549b9e-9590-4ab4-8aaa-f5cea87ba4b6",
"stackTrace": [
" File "/var/task/lambda_function.py", line 154, in lambda_handler\n upload_file(service, download_path, file_name, file_name, folder_id, 'application/vnd.openxmlformats-officedocument.spreadsheetml.sheet')\n",
" File "/var/task/lambda_function.py", line 78, in upload_file\n file = service.files().create(\n",
" File "/opt/python/googleapiclient/_helpers.py", line 131, in positional_wrapper\n return wrapped(*args, **kwargs)\n",
" File "/opt/python/googleapiclient/http.py", line 937, in execute\n raise HttpError(resp, content, uri=self.uri)\n"
]
}

After a bit of digging in, I found that 'Shared Drives' is different from 'Shared with me' and all the APIs I found so far apply to the 'Shared Drives' only. The supportsTeamDrives=True has been deprecated and I was not able to find a related replacement parameter in the docs. There is a parameter sharedWithMe=True for the file.list api and I'm not sure how I can use this in my code because file.create doesn't see the folderID for a 'Shared with me' folder anyway. Any suggestions are appreciated in advance!

My current code:

def upload_file(service, file_name_with_path, file_name, description, folder_id, mime_type):  
    
media_body = MediaFileUpload(file_name_with_path, mimetype=mime_type)

body = {
    'name': file_name,
    'title': file_name,
    'description': description,
    'mimeType': mime_type,
    'parents': [folder_id]
}

file = service.files().create(
    supportsAllDrives=True,
    supportsTeamDrives=True,
    body=body,
    media_body=media_body).execute()

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(2

百思不得你姐 2025-01-20 09:41:55

修改答案以包含更多详细信息:

您是对的,“共享云端硬盘”与“与我共享”不同。首先,您需要从与您共享的文件夹中获取 ID,为此您可以使用 files:list。要将文件上传到该文件夹​​或任何类型的文件夹,您可以使用下面修改后的代码:

from __future__ import print_function
import pickle
import os.path
from googleapiclient.http import MediaFileUpload
from googleapiclient.discovery import build
from google_auth_oauthlib.flow import InstalledAppFlow
from google.auth.transport.requests import Request
from google.oauth2 import credentials, service_account

# Scopes required by this endpoint -> https://developers.google.com/drive/api/v3/reference/files/create
SCOPES = ['https://www.googleapis.com/auth/drive']
"""
To upload/create a file in to a 'Shared with me' folder this script has the following configured:

1. Project:
    * Create project 
    * Enable the Google Workspace API the service account will be using:     https://developers.google.com/workspace/guides/create-project

2.Consent screen:
    * Configure the consent screen for the application 
    * Create credentials for your service account depending on the type of application to be used with https://developers.google.com/workspace/guides/create-credentials#create_a_service_account 
    Once your Service Account is created you are taken back to the credentials list (https://console.cloud.google.com/apis/credential) click on the created Service Account, next click on ‘Advanced settings’ and copy your client ID

3. Scopes
    * Collect the scopes needed for your service account/application
     https://developers.google.com/identity/protocols/oauth2/scopes

4. Grant access to user data to a service account in Google Workspace https://admin.google.com/ac/owl/domainwidedelegation
    * In the "Client ID" field, paste the client ID  from your service account
    * In the "OAuth Scopes" field, enter a comma-delimited list of the scopes required by your application. This is the same set of scopes you defined when configuring the OAuth consent screen.
    * Click Authorize.

5. In your code you need to impersonate the account the folder was shared with, if it was your account, you add your account here:
    credentials = service_account.Credentials.from_service_account_file(
                SERVICE_ACCOUNT_FILE, scopes=SCOPES)
    delegated_creds = credentials.with_subject('[email protected]')
"""

def main():

    SERVICE_ACCOUNT_FILE = 'drive.json' #Service Account credentials from Step 2

    credentials = service_account.Credentials.from_service_account_file(
                SERVICE_ACCOUNT_FILE, scopes=SCOPES)
    delegated_creds = credentials.with_subject('[email protected]')

    service = build('drive', 'v3', credentials=delegated_creds)


    media = MediaFileUpload(
        'xfiles.jpg',
        mimetype='image/jpeg',
        resumable=True
        )
    request = service.files().create(
        media_body=media,
        body={'name': 'xfile new pic', 'parents': ['1Gb0BH1NFz30eau8SbwMgXYXDjTTITByE']} #In here 1Gb0BH1NFz3xxxxxxxxxxx is the 'Shared With ME'FolderID to upload this file to
        )

    response = None
    while response is None:
            status, response = request.next_chunk()
            if status:
                print("Uploaded %d%%." % int(status.progress() * 100))
    print("Upload Complete!")


if __name__ == '__main__':
    main()

其中:

parents 是与您共享的文件夹的 ID。

请参阅此处了解更多文档详细信息

Modified answer to include more details:

You are correct 'Shared Drives' are different from 'Shared With Me'. First off, you need to get the ID from the shared with you folder, for this you can use files:list. To upload files to that folder or any type of folder you can use the modified code below:

from __future__ import print_function
import pickle
import os.path
from googleapiclient.http import MediaFileUpload
from googleapiclient.discovery import build
from google_auth_oauthlib.flow import InstalledAppFlow
from google.auth.transport.requests import Request
from google.oauth2 import credentials, service_account

# Scopes required by this endpoint -> https://developers.google.com/drive/api/v3/reference/files/create
SCOPES = ['https://www.googleapis.com/auth/drive']
"""
To upload/create a file in to a 'Shared with me' folder this script has the following configured:

1. Project:
    * Create project 
    * Enable the Google Workspace API the service account will be using:     https://developers.google.com/workspace/guides/create-project

2.Consent screen:
    * Configure the consent screen for the application 
    * Create credentials for your service account depending on the type of application to be used with https://developers.google.com/workspace/guides/create-credentials#create_a_service_account 
    Once your Service Account is created you are taken back to the credentials list (https://console.cloud.google.com/apis/credential) click on the created Service Account, next click on ‘Advanced settings’ and copy your client ID

3. Scopes
    * Collect the scopes needed for your service account/application
     https://developers.google.com/identity/protocols/oauth2/scopes

4. Grant access to user data to a service account in Google Workspace https://admin.google.com/ac/owl/domainwidedelegation
    * In the "Client ID" field, paste the client ID  from your service account
    * In the "OAuth Scopes" field, enter a comma-delimited list of the scopes required by your application. This is the same set of scopes you defined when configuring the OAuth consent screen.
    * Click Authorize.

5. In your code you need to impersonate the account the folder was shared with, if it was your account, you add your account here:
    credentials = service_account.Credentials.from_service_account_file(
                SERVICE_ACCOUNT_FILE, scopes=SCOPES)
    delegated_creds = credentials.with_subject('[email protected]')
"""

def main():

    SERVICE_ACCOUNT_FILE = 'drive.json' #Service Account credentials from Step 2

    credentials = service_account.Credentials.from_service_account_file(
                SERVICE_ACCOUNT_FILE, scopes=SCOPES)
    delegated_creds = credentials.with_subject('[email protected]')

    service = build('drive', 'v3', credentials=delegated_creds)


    media = MediaFileUpload(
        'xfiles.jpg',
        mimetype='image/jpeg',
        resumable=True
        )
    request = service.files().create(
        media_body=media,
        body={'name': 'xfile new pic', 'parents': ['1Gb0BH1NFz30eau8SbwMgXYXDjTTITByE']} #In here 1Gb0BH1NFz3xxxxxxxxxxx is the 'Shared With ME'FolderID to upload this file to
        )

    response = None
    while response is None:
            status, response = request.next_chunk()
            if status:
                print("Uploaded %d%%." % int(status.progress() * 100))
    print("Upload Complete!")


if __name__ == '__main__':
    main()

Where:

parents is the ID of the folder shared with you.

See here for more documentation details

情徒 2025-01-20 09:41:55

与 Google Workspace API 专家交谈后,发现没有可用的 API 来执行上述任务。为了清楚起见,请参阅我的目标文件夹所在的图片。

“共享云端硬盘”和“与我共享”之间的区别(图片)

以下是来自支持代理:

我审查了您的代码,一切都完成得很完美,所以我与
我们的驱动专家,他们向我解释说“与
我”这不仅仅是一个标签,而且因为你不是所有者
文件的(就像它们位于“我的云端硬盘”中一样)或
共同所有者(如果他们位于“共享驱动器”中)不允许
您可以使用任何类型的 API 来自动创建文件或
删除或任何与此相关的事情。

在这种情况下,您可以在云端硬盘上制作副本并使其自动化
在那里,然后时不时地在文件中更新它
与您共享,或者只是要求用户将其移至“共享云端硬盘”
并从那里访问它。

我承认我有点失望,尽管有权限这样做,但没有 API 方法可以在另一个用户的文件夹中添加/删除/编辑。作为一名开发人员,我的理解是 CLI 是与任何服务交互的最终最强大的方式。 GUI 仅次于 CLI,它只是一种更具视觉吸引力的媒介。很多时候,当我们无法使用 GUI 执行任务时,我们会转向 CLI 来管理高粒度和精度。

但这是一个完全颠倒的场景!我无法理解如何访问“共享文件夹”并通过 GUI 进行添加和删除,但无法使用脚本执行相同的操作。我现在明白,“与我共享”只是一个标签,而不是我访问该文件夹的“位置”,但我肯定会假设有另一种 API 方式来访问属于另一个用户的文件夹(使用该人的用户名) /ID 用于识别,文件夹路径作为目标,验证我是否有权进行所述身份验证更改,如果没有则返回错误,最后执行 API)。

如果有人能够向我解释是否有具体原因导致最终用户无法使用此功能,我很想了解一下。

编辑< /strong>

我在这里发布解决方案有点晚了,但问题是我的 API 正在使用的 google 工作空间服务帐户没有对我尝试的共享驱动器的写入权限来查询。一旦服务帐户被授予所需的编辑权限,我的代码就可以完美运行。

After a chat with a Google Workspace API specialist, turns out there is no API available to perform the above task. For clarity, refer the picture where my target folder lies.

Difference between 'Shared Drive' and 'Shared with me' (image)

Here's the response from the Support Agent:

I reviewed your code and everything was done perfectly, so I spoke to
our Drive Specialists, and they have explained to me that "Shared with
me" it's more than anything a label, and because you are not the owner
of the file, (like you would be if they were in "My Drive" )nor the
co-owner (if they were located in "Shared Drive") it does not allow
you to use any type of API in order to automate file creation or
deletion or anything for that matter.

In this case you can either make a copy on your Drive and automate it
there, and just update it every now and then in the file that was
shared with you, or just ask the user to move it to the "Shared Drive"
and access it from there.

I confess I'm a little disappointed that there is no API way to add/delete/edit in another user's folder in spite of having permissions to do so. My understanding as a developer is that the CLI is the ultimate most powerful way to interact with any service. GUI comes second to CLI, it's just a more visually appealing medium. Often times, when we are not able to perform a task using the GUI, we turn to CLI and manage high granularity and precision.

But this was a completely upside down scenario! I'm failing to understand how I'm able to access the 'shared folder' and make adds and deletes through the GUI but unable to do the same using a script. I understand now that 'Shared with me' is just a label and not a 'location' for me to access the folder but surely I would have assumed there was another API way to access a folder that belonged to another user (using the person's username/ID for identification, folder path as target, verifying if I have permissions to make said changes for authentication, returning an error if I don't, lastly executing the API).

If someone's able to explain to me if there is a specific reason why this is not made available to end users, I would love to learn about it please.

EDIT

I'm a bit late posting the solution here, but the issue turned out to be that the google workspace service account that was being used by my API did not have write permissions to the Shared Drive I was trying to query. Once the service account was given the required edit permissions, my code worked perfectly.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文