管理共享云端硬盘

本指南包含与管理共享云端硬盘相关的任务,例如使用 Google Drive API 创建共享云端硬盘以及管理成员和权限。

如需详细了解共享云端硬盘文件夹限制,请参阅文件夹限制

创建共享云端硬盘

如需创建共享云端硬盘,请使用 drives.create 方法。

Java

drive/snippets/drive_v3/src/main/java/CreateDrive.java
import com.google.api.client.googleapis.json.GoogleJsonResponseException;
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.DriveScopes;
import com.google.api.services.drive.model.Drive;
import com.google.auth.http.HttpCredentialsAdapter;
import com.google.auth.oauth2.GoogleCredentials;
import java.io.IOException;
import java.util.Arrays;
import java.util.UUID;

/* class to demonstrate use-case of Drive's create drive. */
public class CreateDrive {

  /**
   * Create a drive.
   *
   * @return Newly created drive id.
   * @throws IOException if service account credentials file not found.
   */
  public static String createDrive() 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.*/
    GoogleCredentials credentials =
        GoogleCredentials.getApplicationDefault().createScoped(Arrays.asList(DriveScopes.DRIVE));
    HttpRequestInitializer requestInitializer = new HttpCredentialsAdapter(
        credentials);

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

    Drive driveMetadata = new Drive();
    driveMetadata.setName("Project Resources");
    String requestId = UUID.randomUUID().toString();
    try {
      Drive drive = service.drives().create(requestId,
              driveMetadata)
          .execute();
      System.out.println("Drive ID: " + drive.getId());

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

Python

drive/snippets/drive-v3/drive_snippet/create_drive.py
import uuid

import google.auth
from googleapiclient.discovery import build
from googleapiclient.errors import HttpError


def create_drive():
  """Create a drive.
  Returns:
      Id of the created drive

  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)

    drive_metadata = {"name": "Project Resources"}
    request_id = str(uuid.uuid4())
    # pylint: disable=maybe-no-member
    drive = (
        service.drives()
        .create(body=drive_metadata, requestId=request_id, fields="id")
        .execute()
    )
    print(f'Drive ID: {drive.get("id")}')

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

  return drive.get("id")


if __name__ == "__main__":
  create_drive()

Node.js

drive/snippets/drive_v3/drive_snippets/create_drive.js
/**
 * Create a drive.
 * */
async function createDrive() {
  // Get credentials and build service
  // TODO (developer) - Use appropriate auth mechanism for your app

  const {GoogleAuth} = require('google-auth-library');
  const {google} = require('googleapis');
  const uuid = require('uuid');

  const auth = new GoogleAuth({
    scopes: 'https://www.googleapis.com/auth/drive',
  });
  const service = google.drive({version: 'v3', auth});

  const driveMetadata = {
    name: 'Project resources',
  };
  const requestId = uuid.v4();
  try {
    const Drive = await service.drives.create({
      resource: driveMetadata,
      requestId: requestId,
      fields: 'id',
    });
    console.log('Drive Id:', Drive.data.id);
    return Drive.data.id;
  } catch (err) {
    // TODO(developer) - Handle error
    throw err;
  }
}

PHP

drive/snippets/drive_v3/src/DriveCreateDrive.php
use Google\Client;
use Google\Service\Drive;
use Ramsey\Uuid\Uuid;
function createDrive()
{
    try {
        $client = new Client();
        $client->useApplicationDefaultCredentials();
        $client->addScope(Drive::DRIVE);
        $driveService = new Drive($client);

        $driveMetadata = new Drive\Drive(array(
                'name' => 'Project Resources'));
        $requestId = Uuid::uuid4()->toString();
        $drive = $driveService->drives->create($requestId, $driveMetadata, array(
                'fields' => 'id'));
        printf("Drive ID: %s\n", $drive->id);
        return $drive->id;
    } catch(Exception $e)  {
        echo "Error Message: ".$e;
    }  

}

.NET

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

namespace DriveV3Snippets
{
    // Class to demonstrate use of Drive's create drive.
    public class CreateDrive
    {
        /// <summary>
        /// Create a drive.
        /// </summary>
        /// <returns>newly created drive Id.</returns>
        public static string DriveCreateDrive()
        {
            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 driveMetadata = new Drive()
                {
                    Name = "Project Resources"
                };
                var requestId = Guid.NewGuid().ToString();
                var request = service.Drives.Create(driveMetadata, requestId);
                request.Fields = "id";
                var drive = request.Execute();
                Console.WriteLine("Drive ID: " + drive.Id);
                return drive.Id;
            }
            catch (Exception e)
            {
                // TODO(developer) - handle error appropriately
                if (e is AggregateException)
                {
                    Console.WriteLine("Credential Not found");
                }
                else
                {
                    throw;
                }
            }
            return null;
        }
    }
}

drives.create 方法的调用是幂等的。

requestId 参数用于标识创建共享云端硬盘的逻辑尝试。如果请求超时或返回不确定的后端错误,则可以重复相同的请求。requestId 和请求正文必须保持不变。

如果共享云端硬盘已在之前的请求中成功创建或因重试而成功创建,则返回正常响应。有时,例如在长时间后或请求正文发生更改时,系统可能会返回 409 错误,表明必须舍弃 requestId

添加或移除共享云端硬盘成员

使用 permissions 资源添加或移除共享云端硬盘成员。

如需添加成员,请在共享云端硬盘中创建相应权限。权限方法也可用于共享云端硬盘中的单个文件,以授予成员更多权限或允许非成员协作处理特定项目。

如需了解详情和查看示例代码,请参阅共享文件、文件夹和云端硬盘

删除共享云端硬盘

使用 drives.delete 方法删除共享云端硬盘。在删除共享云端硬盘之前,必须将其中的所有内容移至回收站或删除。

面向网域管理员的共享云端硬盘管理

useDomainAdminAccess 参数与 drivespermissions 资源搭配使用,以管理组织中的共享云端硬盘。

如果用户使用 useDomainAdminAccess=true 调用这些方法,则必须具有 Drive and Docs 管理员权限。管理员可以搜索共享云端硬盘或更新其组织拥有的共享云端硬盘的权限,无论管理员是否是任何给定共享云端硬盘的成员。

恢复没有组织者的共享云端硬盘

以下示例演示了如何使用这些资源来恢复不再有组织者的共享云端硬盘。

Java

drive/snippets/drive_v3/src/main/java/RecoverDrive.java
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.DriveScopes;
import com.google.api.services.drive.model.Drive;
import com.google.api.services.drive.model.DriveList;
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 Drive's shared drive without an organizer. */
public class RecoverDrive {

  /**
   * Find all shared drives without an organizer and add one.
   *
   * @param realUser User's email id.
   * @return All shared drives without an organizer.
   * @throws IOException if shared drive not found.
   */
  public static List<Drive> recoverDrives(String realUser)
      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.*/
    GoogleCredentials credentials =
        GoogleCredentials.getApplicationDefault().createScoped(Arrays.asList(DriveScopes.DRIVE));
    HttpRequestInitializer requestInitializer = new HttpCredentialsAdapter(
        credentials);

    // Build a new authorized API client service.
    com.google.api.services.drive.Drive service =
        new com.google.api.services.drive.Drive.Builder(new NetHttpTransport(),
            GsonFactory.getDefaultInstance(),
            requestInitializer)
            .setApplicationName("Drive samples")
            .build();
    List<Drive> drives = new ArrayList<Drive>();

    // Find all shared drives without an organizer and add one.
    // Note: This example does not capture all cases. Shared drives
    // that have an empty group as the sole organizer, or an
    // organizer outside the organization are not captured. A
    // more exhaustive approach would evaluate each shared drive
    // and the associated permissions and groups to ensure an active
    // organizer is assigned.
    String pageToken = null;
    Permission newOrganizerPermission = new Permission()
        .setType("user")
        .setRole("organizer");

    newOrganizerPermission.setEmailAddress(realUser);


    do {
      DriveList result = service.drives().list()
          .setQ("organizerCount = 0")
          .setFields("nextPageToken, drives(id, name)")
          .setUseDomainAdminAccess(true)
          .setPageToken(pageToken)
          .execute();
      for (Drive drive : result.getDrives()) {
        System.out.printf("Found drive without organizer: %s (%s)\n",
            drive.getName(), drive.getId());
        // Note: For improved efficiency, consider batching
        // permission insert requests
        Permission permissionResult = service.permissions()
            .create(drive.getId(), newOrganizerPermission)
            .setUseDomainAdminAccess(true)
            .setSupportsAllDrives(true)
            .setFields("id")
            .execute();
        System.out.printf("Added organizer permission: %s\n",
            permissionResult.getId());

      }

      drives.addAll(result.getDrives());

      pageToken = result.getNextPageToken();
    } while (pageToken != null);

    return drives;
  }
}

Python

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


def recover_drives(real_user):
  """Find all shared drives without an organizer and add one.
  Args:
      real_user:User ID for the new organizer.
  Returns:
      drives object

  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)

    drives = []

    # pylint: disable=maybe-no-member
    page_token = None
    new_organizer_permission = {
        "type": "user",
        "role": "organizer",
        "emailAddress": "user@example.com",
    }
    new_organizer_permission["emailAddress"] = real_user

    while True:
      response = (
          service.drives()
          .list(
              q="organizerCount = 0",
              fields="nextPageToken, drives(id, name)",
              useDomainAdminAccess=True,
              pageToken=page_token,
          )
          .execute()
      )
      for drive in response.get("drives", []):
        print(
            "Found shared drive without organizer: "
            f"{drive.get('title')}, {drive.get('id')}"
        )
        permission = (
            service.permissions()
            .create(
                fileId=drive.get("id"),
                body=new_organizer_permission,
                useDomainAdminAccess=True,
                supportsAllDrives=True,
                fields="id",
            )
            .execute()
        )
        print(f'Added organizer permission: {permission.get("id")}')

      drives.extend(response.get("drives", []))
      page_token = response.get("nextPageToken", None)
      if page_token is None:
        break

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

  return drives


if __name__ == "__main__":
  recover_drives(real_user="gduser1@workspacesamples.dev")

Node.js

drive/snippets/drive_v3/drive_snippets/recover_drives.js
/**
 * Find all shared drives without an organizer and add one.
 * @param{string} userEmail user ID to assign ownership to
 * */
async function recoverDrives(userEmail) {
  // Get credentials and build service
  // TODO (developer) - Use appropriate auth mechanism for your app

  const {GoogleAuth} = require('google-auth-library');
  const {google} = require('googleapis');

  const auth = new GoogleAuth({
    scopes: 'https://www.googleapis.com/auth/drive',
  });
  const service = google.drive({version: 'v3', auth});
  const drives = [];
  const newOrganizerPermission = {
    type: 'user',
    role: 'organizer',
    emailAddress: userEmail, // Example: 'user@example.com'
  };

  let pageToken = null;
  try {
    const res = await service.drives.list({
      q: 'organizerCount = 0',
      fields: 'nextPageToken, drives(id, name)',
      useDomainAdminAccess: true,
      pageToken: pageToken,
    });
    Array.prototype.push.apply(drives, res.data.items);
    for (const drive of res.data.drives) {
      console.log(
          'Found shared drive without organizer:',
          drive.name,
          drive.id,
      );
      await service.permissions.create({
        resource: newOrganizerPermission,
        fileId: drive.id,
        useDomainAdminAccess: true,
        supportsAllDrives: true,
        fields: 'id',
      });
    }
    pageToken = res.nextPageToken;
  } catch (err) {
    // TODO(developer) - Handle error
    throw err;
  }
  return drives;
}

PHP

drive/snippets/drive_v3/src/DriveRecoverDrives.php
use Google\Client;
use Google\Service\Drive;
use Ramsey\Uuid\Uuid;
function recoverDrives()
{
   try {
    $client = new Client();
    $client->useApplicationDefaultCredentials();
    $client->addScope(Drive::DRIVE);
    $driveService = new Drive($client);

    $realUser = readline("Enter user email address: ");

    $drives = array();
    // Find all shared drives without an organizer and add one.
    // Note: This example does not capture all cases. Shared drives
    // that have an empty group as the sole organizer, or an
    // organizer outside the organization are not captured. A
    // more exhaustive approach would evaluate each shared drive
    // and the associated permissions and groups to ensure an active
    // organizer is assigned.
    $pageToken = null;
    $newOrganizerPermission = new Drive\Permission(array(
        'type' => 'user',
        'role' => 'organizer',
        'emailAddress' => 'user@example.com'
    ));
    $newOrganizerPermission['emailAddress'] = $realUser;
    do {
        $response = $driveService->drives->listDrives(array(
            'q' => 'organizerCount = 0',
            'fields' => 'nextPageToken, drives(id, name)',
            'useDomainAdminAccess' => true,
            'pageToken' => $pageToken
        ));
        foreach ($response->drives as $drive) {
            printf("Found shared drive without organizer: %s (%s)\n",
                $drive->name, $drive->id);
            $permission = $driveService->permissions->create($drive->id,
                $newOrganizerPermission,
                array(
                    'fields' => 'id',
                    'useDomainAdminAccess' => true,
                    'supportsAllDrives' => true
                ));
            printf("Added organizer permission: %s\n", $permission->id);
        }
        array_push($drives, $response->drives);
        $pageToken = $response->pageToken;
    } while ($pageToken != null);
    return $drives;
   } catch(Exception $e) {
      echo "Error Message: ".$e;
   }
}

.NET

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

namespace DriveV3Snippets
{
    // Class to demonstrate use-case of Drive's shared drive without an organizer.
    public class RecoverDrives
    {
        /// <summary>
        /// Find all shared drives without an organizer and add one.
        /// </summary>
        /// <param name="realUser">User ID for the new organizer.</param>
        /// <returns>all shared drives without an organizer.</returns>
        public static IList<Drive> DriveRecoverDrives(string realUser)
        {
            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 drives = new List<Drive>();
                // Find all shared drives without an organizer and add one.
                // Note: This example does not capture all cases. Shared drives
                // that have an empty group as the sole organizer, or an
                // organizer outside the organization are not captured. A
                // more exhaustive approach would evaluate each shared drive
                // and the associated permissions and groups to ensure an active
                // organizer is assigned.
                string pageToken = null;
                var newOrganizerPermission = new Permission()
                {
                    Type = "user",
                    Role = "organizer",
                    EmailAddress = realUser
                };

                do
                {
                    var request = service.Drives.List();
                    request.UseDomainAdminAccess = true;
                    request.Q = "organizerCount = 0";
                    request.Fields = "nextPageToken, drives(id, name)";
                    request.PageToken = pageToken;
                    var result = request.Execute();
                    foreach (var drive in result.Drives)
                    {
                        Console.WriteLine(("Found abandoned shared drive: {0} ({1})",
                            drive.Name, drive.Id));
                        // Note: For improved efficiency, consider batching
                        // permission insert requests
                        var permissionRequest = service.Permissions.Create(
                            newOrganizerPermission,
                            drive.Id
                        );
                        permissionRequest.UseDomainAdminAccess = true;
                        permissionRequest.SupportsAllDrives = true;
                        permissionRequest.Fields = "id";
                        var permissionResult = permissionRequest.Execute();
                        Console.WriteLine("Added organizer permission: {0}", permissionResult.Id);
                    }

                    pageToken = result.NextPageToken;
                } while (pageToken != null);

                return drives;
            }
            catch (Exception e)
            {
                // TODO(developer) - handle error appropriately
                if (e is AggregateException)
                {
                    Console.WriteLine("Credential Not found");
                }
                else
                {
                    throw;
                }
            }
            return null;
        }
    }
}

禁止用户下载、打印或复制您的文件

您可以限制用户在共享云端硬盘中下载、打印和复制文件的方式。

如需确定用户是否可以更改组织者为共享云端硬盘设置的下载限制,请检查 capabilities.canChangeDownloadRestriction 布尔值字段。如果 capabilities.canChangeDownloadRestriction 设置为 true,则可以对共享云端硬盘应用下载限制。如需了解详情,请参阅了解文件功能

drives 资源包含一组布尔值 restrictions 字段,用于指示是否可以对共享云端硬盘执行操作。限制适用于共享云端硬盘或共享云端硬盘中的内容。 可以使用 drives.update 方法设置限制。

如需对共享云端硬盘应用下载限制,共享云端硬盘管理员可以使用 DownloadRestriction 对象设置 drives 资源的 restrictions.downloadRestriction 字段。 将 restrictedForReaders 布尔值字段设置为 true 表示限制读者下载和复制。将 restrictedForWriters 布尔值字段设置为 true 可声明作者无法下载和复制。请注意,如果 restrictedForWriters 字段为 true,则读者也无法下载和复制。同样,将 restrictedForWriters 设置为 true 并将 restrictedForReaders 设置为 false 等同于将 restrictedForWritersrestrictedForReaders 都设置为 true

向后兼容性

随着 DownloadRestriction 对象的推出,restrictions.copyRequiresWriterPermission 布尔值字段的功能已更新。

现在,将 restrictions.copyRequiresWriterPermission 设置为 true 会将 DownloadRestriction 对象的 restrictedForReaders 布尔值字段更新为 true,以声明读者无法下载和复制。

copyRequiresWriterPermission 字段设置为 false 会将 restrictedForWritersrestrictedForReaders 字段都更新为 false。这意味着所有用户的下载或复制限制设置都会被移除。

用于控制下载、打印和复制功能的字段

下表列出了影响下载、打印和复制功能的 drives 资源字段:

字段 说明 版本
capabilities.canCopy 当前用户是否可以复制共享云端硬盘中的文件。 v2 和 v3
capabilities.canDownload 当前用户是否可以下载共享云端硬盘中的文件。 v2 和 v3
capabilities.canChangeCopyRequiresWriterPermission 当前用户是否可以更改共享云端硬盘的 copyRequiresWriterPermission 限制。 v2 和 v3
capabilities.canResetDriveRestrictions 当前用户是否可以将共享云端硬盘限制重置为默认值。 v2 和 v3
capabilities.canChangeDownloadRestriction 当前用户是否可以更改共享云端硬盘的下载限制。 仅限 v3
restrictions.copyRequiresWriterPermission 是否禁止读者和评论者复制、打印或下载共享云端硬盘中的文件。当 true 时,它会将此共享云端硬盘中任何文件的同名字段设置为 true v2 和 v3
restrictions.downloadRestriction 共享云端硬盘管理员应用的下载限制。 仅限 v3

文件夹限制

共享云端硬盘文件夹有一些存储空间限制。如需了解相关信息,请参阅 Google 云端硬盘的共享云端硬盘限制

内容数量上限

用户的共享云端硬盘中的每个文件夹所含的内容数上限为 50 万个,包括文件、文件夹和快捷方式。

达到上限后,共享云端硬盘将无法再接受内容。如需再次接收文件,用户必须从相应文件夹中永久删除一些内容。请注意,回收站中的内容会占用存储空间,但永久删除的内容不会。如需了解详情,请参阅将文件和文件夹放入回收站或删除

文件夹深度限制

共享云端硬盘中的文件夹不得包含超过 100 级嵌套的文件夹。 这意味着,子文件夹不能存储在深度超过 99 级的文件夹下。此限制仅适用于子文件夹。

尝试添加超过 100 级的文件夹会返回 teamDriveHierarchyTooDeep HTTP 状态代码响应。