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

每个 Google 云端硬盘文件、文件夹和共享云端硬盘都有关联的 permissions 资源。每个资源都标识特定 typeusergroupdomainanyone)和 roleownerorganizerfileOrganizerwritercommenterreader)的权限。例如,某个文件可能具有一项权限,用于向特定用户 (type=user) 授予只读访问权限 (role=reader),而另一项权限则用于向特定群组的成员 (type=group) 授予向文件添加注释的权限 (role=commenter)。

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

权限的运作方式

文件夹的权限列表会向下传播。所有子文件和子文件夹都会继承父级文件夹的权限。每当权限或层次结构发生变化时,系统都会递归地在所有嵌套文件夹中传播。例如,如果某个文件存在于某个文件夹中,而该文件夹随后被移至另一个文件夹,则新文件夹的权限会传播到该文件。如果新文件夹向文件用户授予新角色(例如“写入者”),则会替换其旧角色。

反之,如果文件从某个文件夹继承了 role=writer,并移到了提供“读者”角色的另一个文件夹,则该文件现在会继承 role=reader

您无法从共享云端硬盘中的文件或文件夹中移除继承的权限。 而是必须在继承这些权限的直接或间接父级上进行调整。您可以从“我的云端硬盘”或“与我共享”下的项目中移除继承权限。

反之,您可以替换“我的云端硬盘”中文件或文件夹的继承权限。因此,如果某个文件从“我的云端硬盘”文件夹继承了 role=writer,您可以为该文件设置 role=reader,以降低其权限级别。

了解文件功能

permissions 资源最终不会决定当前用户是否能够对文件或文件夹执行操作。不过,files 资源包含一组布尔值 capabilities 字段,用于指示是否可以对文件或文件夹执行操作。Google Drive API 会根据与文件或文件夹关联的当前用户的权限资源设置这些字段。

例如,当 Alex 登录您的应用并尝试共享文件时,系统会检查 Alex 的角色是否对该文件拥有相应权限。如果角色允许用户共享文件,系统会根据该角色填充与文件相关的 capabilities,例如 canShare。如果 Alex 想分享文件,您的应用会检查 capabilities,确保 canShare 已设为 true

如需查看检索文件 capabilities 的示例,请参阅获取文件功能

获取文件功能

当您的应用打开文件时,应检查文件的功能并呈现界面,以反映当前用户的权限。例如,如果用户对文件没有 canComment 功能,则界面中应停用评论功能。

如需检查功能,请对 files 资源调用 get() 方法,并将 fileId 路径参数和 fields 参数设置为 capabilities 字段。如需详细了解如何使用 fields 参数返回字段,请参阅返回特定字段

显示示例

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

请求

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
  }
}

共享云端硬盘资源的场景

共享场景有以下五种类型:

  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,才能管理共享云端硬盘成员资格。只有用户和群组可以成为共享云端硬盘的成员。

创建权限

创建权限时,以下两个字段是必需的:

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

  • rolerole 字段用于标识 type 可以执行的操作。例如,具有 type=userrole=reader 的权限会向特定用户授予对文件或文件夹的只读权限。或者,如果权限包含 type=domainrole=commenter,则网域中的所有人都可以对文件添加评论。如需查看角色以及每个角色允许执行的操作的完整列表,请参阅角色和权限

创建 type=usertype=group 权限时,您还必须提供 emailAddress 以将特定用户或群组与权限相关联。

type=domain 中创建权限时,您还必须提供 domain 以将特定网域与权限相关联。

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

  1. 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"
    }
  ]
}

更新权限

如需更新文件或文件夹的权限,您可以更改分配的角色。如需详细了解如何查找角色来源,请参阅确定角色来源

  1. permissions 资源调用 update() 方法,并将 permissionId 路径参数设置为更改权限,将 fileId 路径参数设置为关联的文件、文件夹或共享云端硬盘。如需查找 permissionId,请对 permissions 资源使用 list() 方法,并使用 fileId 路径参数。

  2. 在请求中,标识新的 role

即使用户或群组已经是共享云端硬盘的成员,您也可以授予对共享云端硬盘中个别文件或文件夹的权限。例如,Alex 是某个共享云端硬盘的成员,拥有 role=commenter 访问权限。不过,您的应用可以向 Alex 授予对共享云端硬盘中某个文件的 role=writer 权限。在这种情况下,由于新角色比通过成员资格授予的角色更宽松,因此新权限会成为文件或文件夹的有效角色

显示示例

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

请求

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"
}

确定角色来源

如需更改文件或文件夹的角色,您必须知道角色的来源。对于共享云端硬盘,角色的来源可以基于共享云端硬盘的成员资格、文件夹的角色或文件的角色。

如需确定共享云端硬盘或其中内容的角色来源,请对 permissions 资源调用 get() 方法,并使用 fileIdpermissionId 路径参数,将 fields 参数设置为 permissionDetails 字段。

如需查找 permissionId,请对 permissions 资源使用 list() 方法,并使用 fileId 路径参数。如需提取 list 请求的 permissionDetails 字段,请将 fields 参数设置为 permissions/permissionDetails

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

显示示例

以下代码示例展示了如何确定角色来源。响应会返回 permissions 资源的 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
    }
  ]
}

使用批量请求更新多项权限

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

以下示例展示了如何使用客户端库执行批量权限修改。

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;
        }
    }
}

删除权限

如需撤消对文件或文件夹的访问权限,请对 permissions 资源调用 delete() 方法,并将 fileIdpermissionId 路径参数设置为删除权限。

对于“我的云端硬盘”中的内容,您可以删除继承的权限。删除继承的权限会撤消对相应内容和子内容(如果有)的访问权限。

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

delete() 方法还用于删除直接应用于共享云端硬盘文件或文件夹的权限。

显示示例

以下代码示例展示了如何通过删除 permissionId 来撤消访问权限。如果成功,则响应正文为空。如需确认已移除权限,请对 permissions 资源使用 list() 方法,并使用 fileId 路径参数。

请求

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

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

如果您与他人合作处理敏感项目,可能需要在过一段时间后限制对方对云端硬盘中特定文件的访问权限。对于“我的云端硬盘”中的文件,您可以设置失效日期,以限制或移除对相应文件的访问权限。

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

expirationTime 字段使用 RFC 3339 日期时间表示权限的到期时间。失效时间存在以下限制:

  • 只能对用户和群组权限设置这些属性。
  • 时间必须是将来的时间。
  • 时间不得超过未来 1 年。

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