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

每个 Google 云端硬盘文件、文件夹和共享云端硬盘都有关联的 permissions 资源。每个资源都标识特定 typeusergroupdomainanyone)和 roleownerorganizerfileOrganizerwritercommenterreader)的权限。例如,某个文件可能具有一项权限,用于向特定用户 (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 日期时间表示权限到期时间。失效时间存在以下限制:

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

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

权限传播

文件夹的权限列表会向下传播,并且所有子文件和文件夹都会继承父级文件夹的权限。每当权限或层次结构发生更改时,传播都会通过所有嵌套文件夹递归进行。例如,如果文件存在于一个文件夹中,而该文件夹随后又移到了另一个文件夹中,则对新文件夹的权限将传播到该文件。 如果新文件夹为文件用户授予新角色(例如“写入者”),该角色将覆盖其旧角色。

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

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

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

功能

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

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

如需查看检索文件 capabilities 的示例,请参阅验证用户权限

创建权限

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

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

验证用户权限

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

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

如需检查功能,请对 files 资源调用 get() 方法,并将 fileId 路径参数和 fields 参数设置为 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 资源调用 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
    }
  ]
}

更改权限

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

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

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

即使用户或群组已经是共享云端硬盘的成员,您也可以授予对共享云端硬盘中个别文件或文件夹的权限。例如,Alex 拥有 role=commenter,这是其共享云端硬盘成员资格的一部分。但是,您的应用可授权 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"
}

列出和解决待处理的访问权限提案

访问权限提案是请求者向审批人提出的授予收件人对云端硬盘内容的访问权限的提案。

审批人可以审核云端硬盘文件中所有未解析的访问权限提案并采取相应措施。也就是说,您可以通过程序化方式查询访问权限提案并加以解决,从而加快审批流程。此外,审批人还可以汇总查看提案。

Drive API 提供了 accessproposals 资源,以便您查看和解决待处理的访问权限提案。accessproposals 资源的方法适用于文件、文件夹和共享云端硬盘中的文件,但不适用于共享云端硬盘中的文件。

以下术语专门用于访问权限提案:

  • 请求者:发起对云端硬盘内容的访问权限提议的用户。
  • 收件人:如果访问权限提案获得批准,则获得文件额外权限的用户。很多时候,收件人与请求者相同,但并不总是如此。
  • 批准人:负责批准(或拒绝)访问权限提案的用户。这通常是因为他们是文档的所有者或可以共享文档。

列出待处理的访问权限提案

如需列出云端硬盘项的所有待处理访问权限提议,请对 accessproposals 资源调用 list() 方法,并添加 fileId 路径参数。

只有文件中的审批人才能列出文件中的待处理提案。审批人是指具有文件 can_approve_access_proposals 功能的用户。如果请求者不是审批人,则返回空列表。如需详细了解 capabilities,请参阅功能部分。

响应正文由一个 AccessProposal 对象组成,该对象表示文件上未解决的访问权限建议列表。

AccessProposal 对象包含与每个提案相关的信息,例如请求者、收件人和请求者添加的消息。它还包含一个 AccessProposalRoleAndView 对象,用于将请求者提议的 roleview 分组。由于 role 是一个重复字段,因此每个方案都可能有多个。例如,提案可能包含一个 AccessProposalRoleAndView 对象(role=readerview=published),以及一个仅包含 role=writer 值的额外 AccessProposalRoleAndView 对象。如需了解详情,请参阅视图

传递以下查询参数可自定义访问权限提案的分页或过滤:

  • pageToken:从上一个列表调用收到的页面令牌。提供此令牌可检索后续页面。

  • pageSize:每页返回的访问权限提案数量上限。

解决待处理的访问权限提案

如需解析云端硬盘内容的所有待处理访问权限提议,请对 accessproposals 资源调用 resolve() 方法,并添加 fileIdproposalId 路径参数。

resolve() 方法包含一个 action 查询参数,用于表示对提案要执行的操作。Action 对象会跟踪提案的状态变化,以便我们知道提案是被接受还是被拒绝。

resolve() 方法还包含可选的 roleview 查询参数。仅支持 writercommenterreader 角色。如果未指定角色,则默认为 reader。借助额外的可选查询参数 send_notification,您可以在提案被接受或遭拒时向请求者发送电子邮件通知。

list() 方法一样,解析提案的用户必须具有该文件的 can_approve_access_proposals 功能。如需详细了解 capabilities,请参阅功能部分。

系统会使用共享云端硬盘资源的场景下列出的方法来解决建议。如果同一用户有多个建议,但角色不同,则适用以下规则:

  • 如果一个提案被接受,另一个提案被拒绝,则已接受的角色适用于云端硬盘项。
  • 如果同时接受这两个提案,系统会应用权限更高的提案(例如 role=writer 而非 role=reader)。系统会从相应内容中移除其他访问权限提议。

resolve() 方法发送提案后,共享操作即会完成。系统不再通过 list() 方法返回 AccessProposal。提案被接受后,用户必须使用 permissions 集合来更新文件或文件夹的权限。如需了解详情,请参阅更改权限部分。

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

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

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

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

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

显示示例

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

请求

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)。

将文件所有权从一个个人账号转移到另一个个人账号

您可以在一个个人账号之间转移文件的所有权。不过,在预期所有者明确同意转移之前,云端硬盘不会在两个个人账号之间转移文件的所有权。如需将文件所有权从一个消费者账号转移到另一个消费者账号,请执行以下操作:

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