共享文件、文件夹和云端硬盘

每个 Google 云端硬盘文件、文件夹和共享云端硬盘都与 permissions 资源。每个资源 标识特定 type(用户、群组、网域、任何人)的权限 和 role,例如“评论者”或“阅读器”例如,文件可能含有 向特定用户 (type=user) 授予只读权限 (role=reader) 同时又向特定群组成员授予另一项权限 (type=group) 可向文件添加评论 (role=commenter)。

如需查看角色的完整列表以及每个角色允许的操作,请参阅 角色和权限

共享云端硬盘资源的共享情况

共有五种不同类型的共享方案:

  1. 要共享“我的云端硬盘”中的文件,用户必须拥有 role=writerrole=owner

  2. 要共享“我的云端硬盘”中的文件夹,用户必须满足以下条件: role=writerrole=owner

    • 如果文件的 writersCanShare 布尔值设为 False, 用户必须具有更宽松的 role=owner

    • 不允许进行临时访问(受有效日期和时间限制) 与role=writer共享“我的云端硬盘”文件夹。有关 请参阅 设置失效日期以限制文件访问权限

  3. 如要共享共享云端硬盘中的文件,用户必须拥有 role=writerrole=fileOrganizerrole=organizer

    • writersCanShare 设置不适用于共享云端硬盘中的内容。 系统会将此属性视为始终设为 True
  4. 要共享共享云端硬盘中的文件夹,用户必须拥有role=organizer权限。

    • 如果对sharingFoldersRequiresOrganizerPermission 共享云端硬盘已设为“False”,拥有role=fileOrganizer的用户可以 共享该共享云端硬盘中的文件夹。
  5. 要管理共享云端硬盘成员资格,用户必须拥有 role=organizer 权限。仅限 用户和群组可以成为共享云端硬盘的成员。

设置失效日期以限制文件访问权限

当您与工作人员合作处理敏感项目时,不妨 一段时间后,限制他们对云端硬盘中特定文件的访问权限 。对于“我的云端硬盘”中的文件,您可以将失效日期设为 限制或移除对该文件的访问权限。

如需设置到期日期,请执行以下操作:

expirationTime 字段使用 RFC 3339 指示权限何时到期 日期时间 ,了解所有最新动态。到期时间有以下限制:

  • 只能针对用户和群组权限进行设置。
  • 时间必须是将来的时间。
  • 时间不能超出未来一年内的日期。

如需详细了解失效日期,请参阅以下文章:

权限传播

文件夹的权限列表向下传递,所有子文件和 文件夹会从父级文件夹继承权限。每当权限或 层次结构发生更改,传播会以递归方式通过所有嵌套的 文件夹中。例如,如果文件夹中存在文件,然后又移动了该文件夹, 另一个文件夹中,针对新文件夹的权限将传播到该文件。 如果新文件夹向文件用户授予了新角色(例如“writer”),它 覆盖旧角色。

相反,如果某个文件从文件夹继承 role=writer,然后移至 另一个提供“阅读器”的文件夹则文件现在会继承 role=reader

您无法为共享云端硬盘的文件或文件夹移除继承的权限。 相反,必须针对直接或间接父级调整这些权限, 它们是继承而来的您可为下的内容移除继承的权限 “我的云端硬盘”或“与我共享”

反之,在“我的文件夹”中,可以覆盖文件或文件夹继承的权限 云端硬盘。因此,如果文件继承 role=writer 继承自 My 云端硬盘文件夹,您可以在该文件上设置 role=reader,以降低其 权限级别。

功能

Permissions 资源最终不会 决定当前用户能否对文件或文件夹执行操作。 相反,Files资源包含一系列 布尔值 capabilities 字段,用于指示是否可以 对文件或文件夹执行的操作。Google Drive API 会根据 与文件或文件夹关联的当前用户的权限资源。

例如,当阿力登录您的应用并尝试共享文件时,阿力的角色 检查文件权限。如果该角色允许他们共享文件, 与文件相关的 capabilities(例如 canShare)已填充 角色的相对位置。如果阿力想要分享该文件,您的应用会检查 capabilities,用于确保 canShare 设置为 true

有关检索文件 capabilities 的示例,请参阅验证用户 权限

创建权限

创建权限时,必须使用以下两个字段:

  • typetype 用于标识权限的范围(usergroupdomainanyone)。具有 type=user 的权限适用于特定用户,而 具有 type=domain 的权限会应用于特定网域中的所有人。

  • role - role 字段 标识 type 可以执行的操作。例如, type=user 权限和 role=reader 可授予特定用户 拥有相应文件或文件夹的只读权限。或 type=domain 的权限 而 role=commenter 则允许网域中的所有人在文件中添加评论。对于 有关角色的完整列表以及每个角色允许的操作,请参阅 角色和权限

创建 type=usertype=group 的权限时,您还必须同时 提供一个 emailAddress 来将 向特定用户或群组授予权限

当您创建 type=domain 的权限时,您还必须提供 domain - 用于关联特定网域 该权限。

如需创建权限,请执行以下操作:

  1. 使用 permissions.create 方法 替换为关联文件或文件夹的 fileId
  2. 在请求正文中,指定 typerole
  3. 如果值为 type=usertype=group,请提供 emailAddress。如果为 type=domain, 提供 domain

显示示例

以下代码示例展示了如何创建权限。响应会返回 Permission 资源的实例,包括分配的 permissionId

请求

POST https://www.googleapis.com/drive/v3/files/FILE_ID/permissions
{
  "requests": [
    {
        "type": "user",
        "role": "commenter",
        "emailAddress": "alex@altostrat.com"
    }
  ]
}

答案

{
    "kind": "drive#permission",
    "id": "PERMISSION_ID",
    "type": "user",
    "role": "commenter"
}

使用目标对象群组

目标对象群组是您可以 推荐用户与其共享内容。您可以鼓励用户 针对特定或更具体的受众群体进行宣传,而不是覆盖整个 组织。目标对象群组可以帮助您提高 您的数据,也便于用户恰当地共享内容。有关 请参阅关于目标 受众群体 ,了解所有最新动态。

若要使用目标对象群组,请按以下步骤操作:

  1. 在 Google 管理控制台中,点击“菜单” > 目录 > 目标受众群体

    前往“目标对象群组”

    您必须使用拥有超级用户权限的账号登录,才能执行此任务。

  2. 目标受众群体名单中,点击目标对象群组的名称。接收者 创建目标对象群组,请参阅创建目标对象群组 受众群体

  3. 复制目标受众群体网址中的唯一 ID:https://admin.google.com/ac/targetaudiences/ID

  4. 使用 type=domain 创建权限,并将 domain 字段设置为 ID.audience.googledomains.com

如需了解用户如何与目标对象群组互动,请参阅链接的用户体验 分享 ,了解所有最新动态。

检索文件、文件夹或共享云端硬盘的所有权限

使用 permissions.list 方法 检索文件、文件夹或共享云端硬盘的所有权限。

显示示例

以下代码示例展示了如何获取所有权限。响应会返回权限列表。

请求

GET https://www.googleapis.com/drive/v3/files/FILE_ID/permissions

答案

{
  "kind": "drive#permissionList",
  "permissions": [
    {
      "id": "PERMISSION_ID",
      "type": "user",
      "kind": "drive#permission",
      "role": "commenter"
    }
  ]
}

验证用户权限

当您的应用打开文件时,它应检查文件的 capability 并呈现 以反映当前用户的权限。例如,如果用户 不具备对文件的 canComment 功能, 应在界面中停用

如需详细了解 capabilities,请参阅 Capabilities 部分。

如需检查功能,请使用以下代码调用 files.get: 将 fileIdfields 参数设置为 capabilities 字段。对于 如需详细了解如何使用 fields 参数返回字段,请参阅 返回文件的特定字段

显示示例

以下代码示例展示了如何验证用户权限。响应会返回用户对文件所拥有的功能的列表。每项功能都对应于用户可以执行的精细操作。系统只会为共享云端硬盘中的内容填充部分字段。

请求

GET https://www.googleapis.com/drive/v3/files/FILE_ID?fields=capabilities

答案

{
  "capabilities": {
    "canAcceptOwnership": false,
    "canAddChildren": false,
    "canAddMyDriveParent": false,
    "canChangeCopyRequiresWriterPermission": true,
    "canChangeSecurityUpdateEnabled": false,
    "canComment": true,
    "canCopy": true,
    "canDelete": true,
    "canDownload": true,
    "canEdit": true,
    "canListChildren": false,
    "canModifyContent": true,
    "canModifyContentRestriction": true,
    "canModifyLabels": true,
    "canMoveChildrenWithinDrive": false,
    "canMoveItemOutOfDrive": true,
    "canMoveItemWithinDrive": true,
    "canReadLabels": true,
    "canReadRevisions": true,
    "canRemoveChildren": false,
    "canRemoveMyDriveParent": true,
    "canRename": true,
    "canShare": true,
    "canTrash": true,
    "canUntrash": true
  }
}

确定共享云端硬盘文件和文件夹

若要更改对文件或文件夹的角色,您必须知道角色的来源。 对于共享云端硬盘,角色来源可以基于共享云端硬盘的成员身份 云端硬盘、文件夹中的角色或文件中的角色

确定共享云端硬盘或其中内容的角色来源 驾车,呼叫 permissions.getfileIdpermissionIdfields 参数设置为 permissionDetails 字段。如需查找 permissionId,请使用 使用 fileIdpermissions.list。接收者 提取 permissions.list 请求中的 permissionDetails 字段,设置 将 fields 参数设置为 permissions/permissionDetails

此字段枚举用户的所有继承和直接文件权限, 群组或网域

显示示例

以下代码示例展示了如何确定角色来源。该响应会返回 Permission 资源的 permissionDetailsinheritedFrom 字段提供从中继承权限的项目的 ID。

请求

GET https://www.googleapis.com/drive/v3/files/FILE_ID/permissions/PERMISSION_ID?fields=permissionDetails&supportsAllDrives=true

答案

{
  "permissionDetails": [
    {
      "permissionType": "member",
      "role": "commenter",
      "inheritedFrom": "INHERITED_FROM_ID",
      "inherited": true
    },
    {
      "permissionType": "file",
      "role": "writer",
      "inherited": false
    }
  ]
}

更改权限

如需更改文件或文件夹的权限,您可以更改已分配的角色:

  1. 使用以下代码调用 permissions.update: 需要更改的权限的 permissionId 以及用于更改权限的 fileId 关联的文件、文件夹或共享云端硬盘。如需查找 permissionId,请使用 使用 fileIdpermissions.list

  2. 在请求中,找到新的 role

您可以授予共享云端硬盘中个别文件或文件夹的权限,甚至可以 如果用户或群组已经是成员,则会发生该错误。例如,Alex 有 role=commenter 包含在共享云端硬盘成员资格中。但是,您的应用可以让小伟 role=writer(针对共享云端硬盘中的文件)。在本示例中,由于新角色 比通过其成员资格授予的角色更宽松,新的 权限将成为文件或文件夹的有效角色

显示示例

以下代码示例展示了如何将文件或文件夹的权限从评论者更改为作者。响应会返回 Permission 资源的实例。

请求

PATCH https://www.googleapis.com/drive/v3/files/FILE_ID/permissions/PERMISSION_ID
{
  "requests": [
    {
        "role": "writer"
    }
  ]
}

答案

{
  "kind": "drive#permission",
  "id": "PERMISSION_ID",
  "type": "user",
  "role": "writer"
}

撤消对文件或文件夹的访问权限

要撤消对文件或文件夹的访问权限,请调用 将 delete 替换为 fileIdpermissionId 删除权限。

对于“我的云端硬盘”中的内容,则可以删除继承的 权限。删除继承的权限会撤消对该项的访问权限,并且 子项(如果有)。

对于共享云端硬盘中的内容,继承的权限无法撤消。更新或 改为撤消对父级文件或文件夹的权限。

delete 操作还用于删除直接应用于 共享云端硬盘文件或文件夹。

显示示例

以下代码示例展示了如何通过删除 permissionId 来撤消访问权限。如果成功,响应正文将为空。如需确认权限已移除,请将 permissions.listfileId 搭配使用。

请求

DELETE https://www.googleapis.com/drive/v3/files/FILE_ID/permissions/PERMISSION_ID

将文件所有权转移给同一组织中的其他 Google Workspace 账号

对“我的云端硬盘”中现有文件的所有权可以 一个 Google Workspace 账号 同一组织中的其他账号。拥有共享 云端硬盘拥有其中的文件。因此,系统不支持转移所有权 (针对共享云端硬盘中的文件和文件夹)。共享云端硬盘的组织者可以移动 该共享云端硬盘中的内容,以及各自的“我的云端硬盘”中哪个 将所有权转让给他们。

要转移“我的云端硬盘”中文件的所有权,请执行以下操作之一: 以下:

  • 创建用于向特定用户授予的文件权限 (type=user) 所有者访问权限 (role=owner)。

  • 使用 role=owner 更新现有文件的权限并转移 所有权归指定用户 (transferOwnership=true)。

将文件所有权从一个消费者账号转移到另一个消费者账号

文件所有权可以在个人用户账号之间转移。 不过,云端硬盘不会在 Google 云端硬盘之间转移文件所有权 消费者 账号 直到潜在的新所有者明确同意转移。转移 将文件所有权从一个消费者账号转移到另一个消费者账号:

  1. 当前所有者通过创建或更新请求来启动所有权转让 潜在新所有者的文件权限。该权限必须包含 这些设置:role=writertype=userpendingOwner=true。如果 新所有者正在为潜在所有者创建权限,电子邮件地址 系统会向新的潜在所有者发送通知,告知对方 文件的所有权。

  2. 新所有者接受所有权转让请求,方法是创建或更新 文件的权限。该权限必须包含以下设置: role=ownertransferOwnership=true。如果新所有者创建了 新权限,则系统会向先前的所有者发送电子邮件通知 表明所有权已转让。

文件转移后,之前所有者的角色会降级为“writer”。

通过批量请求更改多项权限

我们强烈建议您使用 批量请求用于修改多个 权限。

以下示例展示了如何使用 客户端库。

Java

drive/snippets/drive_v3/src/main/java/ShareFile.java
import com.google.api.client.googleapis.batch.BatchRequest;
import com.google.api.client.googleapis.batch.json.JsonBatchCallback;
import com.google.api.client.googleapis.json.GoogleJsonError;
import com.google.api.client.googleapis.json.GoogleJsonResponseException;
import com.google.api.client.http.HttpHeaders;
import com.google.api.client.http.HttpRequestInitializer;
import com.google.api.client.http.javanet.NetHttpTransport;
import com.google.api.client.json.gson.GsonFactory;
import com.google.api.services.drive.Drive;
import com.google.api.services.drive.DriveScopes;
import com.google.api.services.drive.model.Permission;
import com.google.auth.http.HttpCredentialsAdapter;
import com.google.auth.oauth2.GoogleCredentials;
import java.io.IOException;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;

/* Class to demonstrate use-case of modify permissions. */
public class ShareFile {

  /**
   * Batch permission modification.
   * realFileId file Id.
   * realUser User Id.
   * realDomain Domain of the user ID.
   *
   * @return list of modified permissions if successful, {@code null} otherwise.
   * @throws IOException if service account credentials file not found.
   */
  public static List<String> shareFile(String realFileId, String realUser, String realDomain)
      throws IOException {
        /* Load pre-authorized user credentials from the environment.
         TODO(developer) - See https://developers.google.com/identity for
         guides on implementing OAuth2 for your application.application*/
    GoogleCredentials credentials = GoogleCredentials.getApplicationDefault()
        .createScoped(Arrays.asList(DriveScopes.DRIVE_FILE));
    HttpRequestInitializer requestInitializer = new HttpCredentialsAdapter(
        credentials);

    // Build a new authorized API client service.
    Drive service = new Drive.Builder(new NetHttpTransport(),
        GsonFactory.getDefaultInstance(),
        requestInitializer)
        .setApplicationName("Drive samples")
        .build();

    final List<String> ids = new ArrayList<String>();


    JsonBatchCallback<Permission> callback = new JsonBatchCallback<Permission>() {
      @Override
      public void onFailure(GoogleJsonError e,
                            HttpHeaders responseHeaders)
          throws IOException {
        // Handle error
        System.err.println(e.getMessage());
      }

      @Override
      public void onSuccess(Permission permission,
                            HttpHeaders responseHeaders)
          throws IOException {
        System.out.println("Permission ID: " + permission.getId());

        ids.add(permission.getId());

      }
    };
    BatchRequest batch = service.batch();
    Permission userPermission = new Permission()
        .setType("user")
        .setRole("writer");

    userPermission.setEmailAddress(realUser);
    try {
      service.permissions().create(realFileId, userPermission)
          .setFields("id")
          .queue(batch, callback);

      Permission domainPermission = new Permission()
          .setType("domain")
          .setRole("reader");

      domainPermission.setDomain(realDomain);

      service.permissions().create(realFileId, domainPermission)
          .setFields("id")
          .queue(batch, callback);

      batch.execute();

      return ids;
    } catch (GoogleJsonResponseException e) {
      // TODO(developer) - handle error appropriately
      System.err.println("Unable to modify permission: " + e.getDetails());
      throw e;
    }
  }
}

Python

drive/snippets/drive-v3/file_snippet/share_file.py
import google.auth
from googleapiclient.discovery import build
from googleapiclient.errors import HttpError


def share_file(real_file_id, real_user, real_domain):
  """Batch permission modification.
  Args:
      real_file_id: file Id
      real_user: User ID
      real_domain: Domain of the user ID
  Prints modified permissions

  Load pre-authorized user credentials from the environment.
  TODO(developer) - See https://developers.google.com/identity
  for guides on implementing OAuth2 for the application.
  """
  creds, _ = google.auth.default()

  try:
    # create drive api client
    service = build("drive", "v3", credentials=creds)
    ids = []
    file_id = real_file_id

    def callback(request_id, response, exception):
      if exception:
        # Handle error
        print(exception)
      else:
        print(f"Request_Id: {request_id}")
        print(f'Permission Id: {response.get("id")}')
        ids.append(response.get("id"))

    # pylint: disable=maybe-no-member
    batch = service.new_batch_http_request(callback=callback)
    user_permission = {
        "type": "user",
        "role": "writer",
        "emailAddress": "user@example.com",
    }
    batch.add(
        service.permissions().create(
            fileId=file_id,
            body=user_permission,
            fields="id",
        )
    )
    domain_permission = {
        "type": "domain",
        "role": "reader",
        "domain": "example.com",
    }
    domain_permission["domain"] = real_domain
    batch.add(
        service.permissions().create(
            fileId=file_id,
            body=domain_permission,
            fields="id",
        )
    )
    batch.execute()

  except HttpError as error:
    print(f"An error occurred: {error}")
    ids = None

  return ids


if __name__ == "__main__":
  share_file(
      real_file_id="1dUiRSoAQKkM3a4nTPeNQWgiuau1KdQ_l",
      real_user="gduser1@workspacesamples.dev",
      real_domain="workspacesamples.dev",
  )

Node.js

drive/snippets/drive_v3/file_snippets/share_file.js
/**
 * Batch permission modification
 * @param{string} fileId file ID
 * @param{string} targetUserEmail username
 * @param{string} targetDomainName domain
 * @return{list} permission id
 * */
async function shareFile(fileId, targetUserEmail, targetDomainName) {
  const {GoogleAuth} = require('google-auth-library');
  const {google} = require('googleapis');

  // Get credentials and build service
  // TODO (developer) - Use appropriate auth mechanism for your app
  const auth = new GoogleAuth({
    scopes: 'https://www.googleapis.com/auth/drive',
  });
  const service = google.drive({version: 'v3', auth});
  const permissionIds = [];

  const permissions = [
    {
      type: 'user',
      role: 'writer',
      emailAddress: targetUserEmail, // 'user@partner.com',
    },
    {
      type: 'domain',
      role: 'writer',
      domain: targetDomainName, // 'example.com',
    },
  ];
  // Note: Client library does not currently support HTTP batch
  // requests. When possible, use batched requests when inserting
  // multiple permissions on the same item. For this sample,
  // permissions are inserted serially.
  for (const permission of permissions) {
    try {
      const result = await service.permissions.create({
        resource: permission,
        fileId: fileId,
        fields: 'id',
      });
      permissionIds.push(result.data.id);
      console.log(`Inserted permission id: ${result.data.id}`);
    } catch (err) {
      // TODO(developer): Handle failed permissions
      console.error(err);
    }
  }
  return permissionIds;
}

PHP

drive/snippets/drive_v3/src/DriveShareFile.php
use Google\Client;
use Google\Service\Drive;
function shareFile()
{
    try {
        $client = new Client();
        $client->useApplicationDefaultCredentials();
        $client->addScope(Drive::DRIVE);
        $driveService = new Drive($client);
        $realFileId = readline("Enter File Id: ");
        $realUser = readline("Enter user email address: ");
        $realDomain = readline("Enter domain name: ");
        $ids = array();
            $fileId = '1sTWaJ_j7PkjzaBWtNc3IzovK5hQf21FbOw9yLeeLPNQ';
            $fileId = $realFileId;
            $driveService->getClient()->setUseBatch(true);
            try {
                $batch = $driveService->createBatch();

                $userPermission = new Drive\Permission(array(
                    'type' => 'user',
                    'role' => 'writer',
                    'emailAddress' => 'user@example.com'
                ));
                $userPermission['emailAddress'] = $realUser;
                $request = $driveService->permissions->create(
                    $fileId, $userPermission, array('fields' => 'id'));
                $batch->add($request, 'user');
                $domainPermission = new Drive\Permission(array(
                    'type' => 'domain',
                    'role' => 'reader',
                    'domain' => 'example.com'
                ));
                $userPermission['domain'] = $realDomain;
                $request = $driveService->permissions->create(
                    $fileId, $domainPermission, array('fields' => 'id'));
                $batch->add($request, 'domain');
                $results = $batch->execute();

                foreach ($results as $result) {
                    if ($result instanceof Google_Service_Exception) {
                        // Handle error
                        printf($result);
                    } else {
                        printf("Permission ID: %s\n", $result->id);
                        array_push($ids, $result->id);
                    }
                }
            } finally {
                $driveService->getClient()->setUseBatch(false);
            }
            return $ids;
    } catch(Exception $e) {
        echo "Error Message: ".$e;
    }

}

.NET

drive/snippets/drive_v3/DriveV3Snippets/ShareFile.cs
using Google.Apis.Auth.OAuth2;
using Google.Apis.Drive.v3;
using Google.Apis.Drive.v3.Data;
using Google.Apis.Requests;
using Google.Apis.Services;

namespace DriveV3Snippets
{
    // Class to demonstrate use-case of Drive modify permissions.
    public class ShareFile
    {
        /// <summary>
        /// Batch permission modification.
        /// </summary>
        /// <param name="realFileId">File id.</param>
        /// <param name="realUser">User id.</param>
        /// <param name="realDomain">Domain id.</param>
        /// <returns>list of modified permissions, null otherwise.</returns>
        public static IList<String> DriveShareFile(string realFileId, string realUser, string realDomain)
        {
            try
            {
                /* Load pre-authorized user credentials from the environment.
                 TODO(developer) - See https://developers.google.com/identity for
                 guides on implementing OAuth2 for your application. */
                GoogleCredential credential = GoogleCredential.GetApplicationDefault()
                    .CreateScoped(DriveService.Scope.Drive);

                // Create Drive API service.
                var service = new DriveService(new BaseClientService.Initializer
                {
                    HttpClientInitializer = credential,
                    ApplicationName = "Drive API Snippets"
                });

                var ids = new List<String>();
                var batch = new BatchRequest(service);
                BatchRequest.OnResponse<Permission> callback = delegate(
                    Permission permission,
                    RequestError error,
                    int index,
                    HttpResponseMessage message)
                {
                    if (error != null)
                    {
                        // Handle error
                        Console.WriteLine(error.Message);
                    }
                    else
                    {
                        Console.WriteLine("Permission ID: " + permission.Id);
                    }
                };
                Permission userPermission = new Permission()
                {
                    Type = "user",
                    Role = "writer",
                    EmailAddress = realUser
                };

                var request = service.Permissions.Create(userPermission, realFileId);
                request.Fields = "id";
                batch.Queue(request, callback);

                Permission domainPermission = new Permission()
                {
                    Type = "domain",
                    Role = "reader",
                    Domain = realDomain
                };
                request = service.Permissions.Create(domainPermission, realFileId);
                request.Fields = "id";
                batch.Queue(request, callback);
                var task = batch.ExecuteAsync();
                task.Wait();
                return ids;
            }
            catch (Exception e)
            {
                // TODO(developer) - handle error appropriately
                if (e is AggregateException)
                {
                    Console.WriteLine("Credential Not found");
                }
                else
                {
                    throw;
                }
            }
            return null;
        }
    }
}