首页 > 解决方案 > 无法将文件所有权从服务帐户转移到 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'。

标签: google-drive-apigoogle-api-php-clientservice-accounts

解决方案


您无法更改位于共享云端硬盘上的文件的所有者

根据文档

共享云端硬盘中的文件归共享云端硬盘所有,而不是个人用户所有。

因此,无需从服务帐户中“夺走”所有权。

您可以赋予用户任何其他角色,例如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 的所有权从服务帐户转移给用户。
  • 作为一种解决方法,用户可以复制服务帐户上传的文件 - 随后服务帐户可以删除原始文件。

推荐阅读