google-drive-api - 无法将文件所有权从服务帐户转移到 Google Drive 用户
问题描述
尝试转让所有权时,出现以下错误:
"domain": "global",
"reason": "invalidSharingRequest",
"message": "Bad Request. User message: \"You can't change the owner of this item.\""
这是我的代码:
use Google_Client;
use Google_Service_Drive;
use Google_Service_Drive_DriveFile;
use Google_Service_Drive_Permission;
public function uploadDocument() {
$FOLDER_ID = 'my_folder_ID_string';
$client = new Google_Client();
$client->setAuthConfig(base_path('service_account_credentials.json'));
$client->setScopes(array('https://www.googleapis.com/auth/drive'));
$service = new Google_Service_Drive($client);
$fileMetadata = new Google_Service_Drive_DriveFile(array(
'name' => 'Test.pdf',
'parents' => [$FOLDER_ID]
));
$content = file_get_contents(public_path('tmp/Test.pdf'));
$file = $service->files->create($fileMetadata, array(
'data' => $content,
'mimeType' => 'application/pdf',
'uploadType' => 'multipart',
'fields' => 'id'
));
// Transfer Ownership
$newPermission = new Google_Service_Drive_Permission();
$newPermission->setRole('owner');
$newPermission->setType('user');
$newPermission->setEmailAddress('email@gmail.com');
$optParams = array('transferOwnership' => 'true');
$service->permissions->create($file->id, $newPermission, $optParams);
}
该文件夹已成功上传到共享文件夹中的 Google Drive(所有者是'email@gmail.com',服务帐户是'editor'),但是上传文件的所有者是服务帐户,编辑者是'email@gmail .com'。
解决方案
您无法更改位于共享云端硬盘上的文件的所有者
根据文档:
共享云端硬盘中的文件归共享云端硬盘所有,而不是个人用户所有。
因此,无需从服务帐户中“夺走”所有权。
您可以赋予用户任何其他角色,例如organizer
,这将允许用户将文件移出共享驱动器,从而成为文件的所有者。\
更新
如果文件是由服务帐户上传到用户云端硬盘上的共享文件夹而不是共享云端硬盘,情况就不同了。
具体来说:
- 对于 GSuite 用户,不允许将所有权转移到域外,这将导致错误
Ownership can only be transferred to another user in the same organization as the current owner.
。 - 服务帐户不被视为域用户,因此受到相同的限制。
- 对于消费者用户,允许将所有权从服务帐户转移给用户,但受到限制: 仅对于 Google mimeType 的文档,可以更改所有者。
- 由于上述将所有权从服务帐户转移给用户的限制,最好通过使用模拟来避免该问题。
- 模拟是指服务帐户代表用户(例如您)行事,当他将文件上传到您的云端硬盘时,相当于您自己上传文件 - 无需转让所有权,无需明确共享文件夹服务帐户是必需的。
- 要设置模拟,您需要
在 GCP 控制台中为特定服务帐号启用域范围的委托。
继续在您的管理控制台中授权服务帐户所需的所有范围
Security > API Controls > Domain wide delegation
。通过添加行来修改您的代码
$client->setSubject($EmailOfUserToImpersonate);
- 请注意,不幸的是,域范围的委派仅适用于域 - 即 GSuite 帐户。
- 对于消费者 (gmail) 帐户,无法将非 Google mimeType 的所有权从服务帐户转移给用户。
- 作为一种解决方法,用户可以复制服务帐户上传的文件 - 随后服务帐户可以删除原始文件。
推荐阅读
- python - 如何通过拟合实验数据来估计一组复杂微分方程的参数?
- python - 如何验证 django DRF 中的字段,同时它可以将电子邮件或电话作为值
- javascript - 我需要忽略 GIT 中的 .cache 文件夹吗
- java - 如何在 jsonb postgresql 中查询并转换为谓词 JPA
- mysql - 对于 mysql 中的字符串列类型,NOT IN 没有按预期工作
- casting - 在 Logistic 回归中将连续数据转换为分类数据时出错
- javascript - React.js 中未更新状态
- r - 如何从 gbm 中获取与训练分数相对应的响应变量的向量?
- bash - 使用文件输入和文件输出在终端中运行程序,并限制输出大小
- python - 如何比较 input() 和 .readline()?