Tìm tệp và thư mục

Hướng dẫn này giải thích cách API Google Drive hỗ trợ một số cách tìm tệp và thư mục.

Bạn có thể sử dụng phương thức list trên tài nguyên files để trả về tất cả hoặc một số tệp và thư mục của người dùng Drive. Bạn cũng có thể sử dụng list phương thức để truy xuất fileId cần thiết cho một số phương thức tài nguyên (chẳng hạn như get và update phương thức).

Sử dụng tham số fields

Nếu muốn chỉ định các trường cần trả về trong phản hồi, bạn có thể đặt fields tham số hệ thống bằng bất kỳ phương thức nào của tài nguyên files. Nếu bạn bỏ qua tham số fields, máy chủ sẽ trả về một tập hợp trường mặc định dành riêng cho phương thức đó. Ví dụ: phương thức list chỉ trả về các trường kind, id, name, mimeType, và resourceKey cho mỗi tệp. Để trả về các trường khác, hãy xem phần Trả về các trường cụ thể.

Lấy tệp theo mã

Để lấy tệp, hãy sử dụng phương thức get trên tài nguyên files bằng tham số đường dẫn fileId. Nếu không biết mã tệp, bạn có thể liệt kê tất cả các tệp bằng list phương thức.

Phương thức này trả về tệp dưới dạng một thực thể của tài nguyên files. Nếu bạn cung cấp tham số alt=media, thì phản hồi sẽ bao gồm nội dung tệp trong nội dung phản hồi. Để tải tệp blob xuống, hãy xem phần Tải nội dung tệp blob xuống.

Để xác nhận rủi ro khi tải phần mềm độc hại đã biết hoặc các tệp lạm dụng khác xuống, hãy đặt tham số acknowledgeAbuse truy vấn thành true. Trường này chỉ áp dụng khi bạn đặt tham số alt=media và người dùng là chủ sở hữu tệp hoặc người tổ chức bộ nhớ dùng chung nơi tệp đó cư trú.

Liệt kê tất cả tệp và thư mục trong Drive của tôi

Sử dụng phương thức list mà không có tham số nào để trả về tất cả tệp và thư mục trong Drive của tôi của người dùng hiện tại.

Lệnh curl sau đây cho biết cách liệt kê tất cả các tệp:

curl -X GET \
  'https://www.googleapis.com/drive/v3/files' \
  -H 'Authorization: Bearer ACCESS_TOKEN' \
  -H 'Accept: application/json'

Thay thế ACCESS_TOKEN bằng mã truy cập OAuth 2.0 được uỷ quyền .

Tìm kiếm các tệp và thư mục cụ thể trong Drive của tôi

Để tìm kiếm một tập hợp tệp hoặc thư mục cụ thể trong Drive của tôi của người dùng hiện tại, hãy sử dụng trường chuỗi truy vấn q bằng phương thức list để lọc các tệp cần trả về bằng cách kết hợp một hoặc nhiều cụm từ tìm kiếm.

Cú pháp chuỗi truy vấn chứa 3 phần sau:

query_term operator values

Trong trường hợp:

  • query_term là cụm từ tìm kiếm hoặc trường cần tìm.

  • operator chỉ định điều kiện cho cụm từ tìm kiếm.

  • values là các giá trị cụ thể mà bạn muốn sử dụng để lọc kết quả tìm kiếm.

Ví dụ: chuỗi truy vấn sau đây sẽ lọc nội dung tìm kiếm để chỉ trả về các thư mục bằng cách đặt loại MIME:

mimeType = 'application/vnd.google-apps.folder'

Để xem tất cả các cụm từ tìm kiếm tệp, hãy xem phần Cụm từ tìm kiếm dành riêng cho tệp.

Để xem tất cả các toán tử truy vấn mà bạn có thể sử dụng để tạo truy vấn, hãy xem phần Toán tử truy vấn.

Ví dụ về chuỗi truy vấn

Bảng sau đây liệt kê các ví dụ về một số chuỗi truy vấn cơ bản. Mã thực tế sẽ khác nhau tuỳ thuộc vào thư viện ứng dụng mà bạn sử dụng cho nội dung tìm kiếm.

Bạn cũng phải thoát các ký tự đặc biệt trong tên tệp để đảm bảo truy vấn hoạt động chính xác. Ví dụ: nếu tên tệp chứa cả dấu nháy đơn (') và dấu gạch chéo ngược ("\"), hãy sử dụng dấu gạch chéo ngược để thoát các ký tự đó: name contains 'quinn\'s paper\\essay'.

Nội dung cần truy vấn Ví dụ
Toán tử so khớp chuỗi (contains)
Các tệp có chứa từ "hello" fullText contains 'hello'
Các tệp có chứa cụm từ chính xác "hello world" fullText contains '"hello world"'
Các tệp có truy vấn chứa ký tự "\" (ví dụ: "\authors") fullText contains '\\authors'
Các tệp có tên chứa "budget" name contains 'budget'
Toán tử bằng và không bằng (=, !=)
Các tệp có tên "hello" name = 'hello'
Các tệp là thư mục mimeType = 'application/vnd.google-apps.folder'
Các tệp không phải là thư mục mimeType != 'application/vnd.google-apps.folder'
Các tệp được gắn dấu sao starred = true
Các tệp nằm trong thùng rác trashed = true
Các tệp không nằm trong thùng rác trashed = false
Các lối tắt trỏ đến một mã tệp cụ thể shortcutDetails.targetId = '1987654321'
Các tệp chưa được chia sẻ với bất kỳ ai hoặc miền nào (riêng tư hoặc được chia sẻ với người dùng hoặc nhóm cụ thể) visibility = 'limited'
Các tệp mà bất kỳ ai có đường liên kết đều có thể truy cập visibility = 'anyoneWithLink'
Các tệp có thể được tìm thấy công khai trên web visibility = 'anyoneCanFind'
Toán tử so sánh (>, >=, <, <=)
Các tệp được sửa đổi sau một ngày nhất định (múi giờ mặc định là UTC) modifiedTime > '2012-06-04T12:00:00'
Các tệp được tạo sau ngày 1 tháng 1 năm 2023 createdTime > '2023-01-01T00:00:00'
Các tệp được sửa đổi trước ngày 1 tháng 1 năm 2023 modifiedTime < '2023-01-01T00:00:00'
Toán tử thành viên tập hợp (in)
Các tệp con trực tiếp trong một tập hợp (ví dụ: mã thư mục trong tập hợp parents) '1234567' in parents
Các tệp trong thư mục dữ liệu ứng dụng 'appDataFolder' in parents
Các tệp mà người dùng "test@example.org" là chủ sở hữu 'test@example.org' in owners
Các tệp mà người dùng "test@example.org" có quyền ghi 'test@example.org' in writers
Các tệp mà thành viên của nhóm "group@example.org" có quyền ghi 'group@example.org' in writers
Các tệp mà người dùng "test@example.org" có quyền đọc 'test@example.org' in readers
Toán tử so khớp tập hợp (has)
Các tệp có thuộc tính tệp tuỳ chỉnh mà tất cả ứng dụng đều có thể nhìn thấy properties has { key='mass' and value='1.3kg' }
Các tệp có thuộc tính tệp tuỳ chỉnh riêng tư đối với ứng dụng yêu cầu appProperties has { key='additionalID' and value='8e8aceg2af2ge72e78' }
Các tệp có thuộc tính tệp tuỳ chỉnh có khoá "department" (bất kể giá trị) properties has { key='department' }
Toán tử logic (and, or, not)
Các tệp có tên chứa các từ "hello" và "goodbye" name contains 'hello' and name contains 'goodbye'
Các tệp có tên không chứa từ "hello" not name contains 'hello'
Các tệp có chứa văn bản "important" và nằm trong thùng rác fullText contains 'important' and trashed = true
Các tệp không chứa từ "hello" not fullText contains 'hello'
Các tệp hình ảnh hoặc video được sửa đổi sau một ngày cụ thể modifiedTime > '2012-06-04T12:00:00' and (mimeType contains 'image/' or mimeType contains 'video/')
Các tệp được chia sẻ với người dùng được uỷ quyền có tên chứa "hello" sharedWithMe and name contains 'hello'
Các tệp là thư mục hoặc lối tắt mimeType = 'application/vnd.google-apps.folder' or mimeType = 'application/vnd.google-apps.shortcut'
Các tệp có tên "Project Plan" không nằm trong thùng rác name = 'Project Plan' and trashed = false
Các tệp con trực tiếp trong một thư mục cụ thể không nằm trong thùng rác '1234567' in parents and trashed = false

Lọc kết quả tìm kiếm bằng thư viện ứng dụng

Mẫu mã sau đây cho biết cách sử dụng thư viện ứng dụng để lọc kết quả tìm kiếm theo tên tệp và mã của tệp JPEG. Mẫu này sử dụng cụm từ tìm kiếm mimeType để thu hẹp kết quả theo các tệp thuộc loại image/jpeg. Mẫu này cũng đặt spaces thành drive để thu hẹp phạm vi tìm kiếm hơn nữa thành không gian Drive space. Khi nextPageToken trả về null, sẽ không có kết quả nào nữa.

Java

drive/snippets/drive_v3/src/main/java/SearchFile.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.Drive;
import com.google.api.services.drive.DriveScopes;
import com.google.api.services.drive.model.File;
import com.google.api.services.drive.model.FileList;
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 search files. */
public class SearchFile {

  /**
   * Search for specific set of files.
   *
   * @return search result list.
   * @throws IOException if service account credentials file not found.
   */
  public static List<File> searchFile() 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_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();

    List<File> files = new ArrayList<File>();

    String pageToken = null;
    do {
      FileList result = service.files().list()
          .setQ("mimeType='image/jpeg'")
          .setSpaces("drive")
          .setFields("nextPageToken, files(id, title)")
          .setPageToken(pageToken)
          .execute();
      for (File file : result.getFiles()) {
        System.out.printf("Found file: %s (%s)\n",
            file.getName(), file.getId());
      }

      files.addAll(result.getFiles());

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

    return files;
  }
}

Python

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


def search_file():
  """Search file in drive location

  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)
    files = []
    page_token = None
    while True:
      # pylint: disable=maybe-no-member
      response = (
          service.files()
          .list(
              q="mimeType='image/jpeg'",
              spaces="drive",
              fields="nextPageToken, files(id, name)",
              pageToken=page_token,
          )
          .execute()
      )
      for file in response.get("files", []):
        # Process change
        print(f'Found file: {file.get("name")}, {file.get("id")}')
      files.extend(response.get("files", []))
      page_token = response.get("nextPageToken", None)
      if page_token is None:
        break

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

  return files


if __name__ == "__main__":
  search_file()

Node.js

drive/snippets/drive_v3/file_snippets/search_file.js
import {GoogleAuth} from 'google-auth-library';
import {google} from 'googleapis';

/**
 * Searches for files in Google Drive.
 * @return {Promise<object[]>} A list of files.
 */
async function searchFile() {
  // Authenticate with Google and get an authorized client.
  // TODO (developer): Use an appropriate auth mechanism for your app.
  const auth = new GoogleAuth({
    scopes: 'https://www.googleapis.com/auth/drive',
  });

  // Create a new Drive API client (v3).
  const service = google.drive({version: 'v3', auth});

  // Search for files with the specified query.
  const result = await service.files.list({
    q: "mimeType='image/jpeg'",
    fields: 'nextPageToken, files(id, name)',
    spaces: 'drive',
  });

  // Print the name and ID of each found file.
  (result.data.files ?? []).forEach((file) => {
    console.log('Found file:', file.name, file.id);
  });

  return result.data.files ?? [];
}

PHP

drive/snippets/drive_v3/src/DriveSearchFiles.php
<?php
use Google\Client;
use Google\Service\Drive;
function searchFiles()
{
    try {
        $client = new Client();
        $client->useApplicationDefaultCredentials();
        $client->addScope(Drive::DRIVE);
        $driveService = new Drive($client);
        $files = array();
        $pageToken = null;
        do {
            $response = $driveService->files->listFiles(array(
                'q' => "mimeType='image/jpeg'",
                'spaces' => 'drive',
                'pageToken' => $pageToken,
                'fields' => 'nextPageToken, files(id, name)',
            ));
            foreach ($response->files as $file) {
                printf("Found file: %s (%s)\n", $file->name, $file->id);
            }
            array_push($files, $response->files);

            $pageToken = $response->pageToken;
        } while ($pageToken != null);
        return $files;
    } catch(Exception $e) {
       echo "Error Message: ".$e;
    }
}

Liệt kê các tệp trong thư mục công khai

Để tìm kiếm hoặc liệt kê các tệp trong thư mục được chia sẻ công khai (trong đó quyền truy cập được đặt thành "Bất kỳ ai có đường liên kết" hoặc "Công khai trên web"), hãy sử dụng phương thức list trên tài nguyên files với tham số truy vấn q được đặt để lọc theo mã của thư mục trong tập hợp parents:

'FOLDER_ID' in parents and trashed = false

Khi liệt kê các tệp trong thư mục công khai, bạn có thể xác thực các yêu cầu bằng khoá API thay vì thông tin xác thực người dùng OAuth 2.0. Nếu thư mục nằm trong bộ nhớ dùng chung, bạn cũng phải đặt supportsAllDrives=true và includeItemsFromAllDrives=true cho yêu cầu.

Các mã mẫu sau đây cho biết cách liệt kê các tệp trong thư mục công khai:

Node.js

/**
 * List files in a public folder using an API key.
 * @param {string} folderId The ID of the public folder.
 * @param {string} apiKey Your Google Cloud API key.
 * @return {Promise<Array>} The list of files.
 */
async function listPublicFolder(folderId, apiKey) {
  const {google} = require('googleapis');
  const service = google.drive({version: 'v3', auth: apiKey});

  try {
    const response = await service.files.list({
      q: `'${folderId}' in parents and trashed = false`,
      fields: 'nextPageToken, files(id, name, mimeType)',
      supportsAllDrives: true,
      includeItemsFromAllDrives: true,
    });
    const files = response.data.files;
    console.log('Files:');
    for (const file of files) {
      console.log(`${file.name} (${file.id})`);
    }
    return files;
  } catch (err) {
    // TODO(developer): Handle error
    console.error(err);
  }
}

curl

curl -G \
  'https://www.googleapis.com/drive/v3/files' \
  --data-urlencode "q='FOLDER_ID' in parents and trashed = false" \
  --data-urlencode 'supportsAllDrives=true' \
  --data-urlencode 'includeItemsFromAllDrives=true' \
  --data-urlencode 'fields=nextPageToken,files(id,name,mimeType)' \
  --data-urlencode 'key=API_KEY' \
  -H 'Accept: application/json'

Thay thế nội dung sau:

Cụm từ tìm kiếm parents chỉ trả về các tệp và thư mục con trực tiếp nằm trong thư mục đã chỉ định. API Drive không cung cấp toán tử hoặc tham số truy vấn để tìm kiếm đệ quy các cây thư mục con trong một Lệnh gọi API.

Để tìm kiếm một thư mục và tất cả các tệp và thư mục con của thư mục đó, ứng dụng của bạn phải thực hiện quá trình duyệt cây ở phía máy khách:

  1. Truy vấn các tệp con trực tiếp của thư mục mục tiêu bằng cách sử dụng 'FOLDER_ID' in parents and trashed = false.
  2. Xác định các thư mục con bằng cách lọc kết quả trong đó mimeType = 'application/vnd.google-apps.folder'.
  3. Truy vấn đệ quy hoặc lặp lại mã của từng thư mục con để truy xuất nội dung của thư mục đó.

Các mã mẫu sau đây minh hoạ cách tìm kiếm đệ quy một thư mục và các phần tử con của thư mục đó:

Node.js

/**
 * Recursively searches a folder and all descendant subfolders for files.
 * @param {string} folderId The ID of the starting folder.
 * @param {Object} authClient An authorized OAuth 2.0 client.
 * @return {Promise<Array>} The list of all descendant files.
 */
async function searchFolderRecursively(folderId, authClient) {
  const {google} = require('googleapis');
  const service = google.drive({version: 'v3', auth: authClient});
  const allFiles = [];
  const foldersToSearch = [folderId];

  try {
    while (foldersToSearch.length > 0) {
      const currentFolderId = foldersToSearch.pop();
      let pageToken = null;

      do {
        const response = await service.files.list({
          q: `'${currentFolderId}' in parents and trashed = false`,
          fields: 'nextPageToken, files(id, name, mimeType)',
          pageSize: 1000,
          supportsAllDrives: true,
          includeItemsFromAllDrives: true,
          pageToken: pageToken,
        });

        const files = response.data.files || [];
        for (const file of files) {
          if (file.mimeType === 'application/vnd.google-apps.folder') {
            foldersToSearch.push(file.id);
          } else {
            allFiles.push(file);
          }
        }

        pageToken = response.data.nextPageToken;
      } while (pageToken);
    }
    return allFiles;
  } catch (err) {
    // TODO(developer): Handle error
    console.error(err);
    throw err;
  }
}

Python

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

def search_folder_recursively(folder_id, creds):
    """Recursively searches a folder and all descendant subfolders for
    files.

    Args:
        folder_id: The ID of the starting folder.
        creds: An authorized OAuth 2.0 credentials object.

    Returns:
        A list of all descendant file resources.
    """
    service = build("drive", "v3", credentials=creds)
    all_files = []
    folders_to_search = [folder_id]

    try:
        while folders_to_search:
            current_folder_id = folders_to_search.pop()
            page_token = None

            while True:
                response = (
                    service.files()
                    .list(
                        q=f"'{current_folder_id}' in parents and trashed = false",
                        fields="nextPageToken, files(id, name, mimeType)",
                        pageSize=1000,
                        supportsAllDrives=True,
                        includeItemsFromAllDrives=True,
                        pageToken=page_token,
                    )
                    .execute()
                )

                for item in response.get("files", []):
                    if (
                        item.get("mimeType")
                        == "application/vnd.google-apps.folder"
                    ):
                        folders_to_search.append(item.get("id"))
                    else:
                        all_files.append(item)

                page_token = response.get("nextPageToken")
                if not page_token:
                    break

        return all_files
    except HttpError as error:
        # TODO(developer): Handle error
        print(f"An error occurred: {error}")
        return None

Tìm tệp có thuộc tính tuỳ chỉnh

Để tìm tệp có thuộc tính tệp tuỳ chỉnh, hãy sử dụng cụm từ tìm kiếm properties hoặc appProperties có khoá và giá trị. Ví dụ: để tìm một thuộc tính tệp tuỳ chỉnh riêng tư đối với ứng dụng yêu cầu có tên là additionalID với giá trị là 8e8aceg2af2ge72e78:

appProperties has { key='additionalID' and value='8e8aceg2af2ge72e78' }

Để biết thêm thông tin, hãy xem phần Thêm thuộc tính tệp tuỳ chỉnh.

Tìm tệp theo nhãn hoặc giá trị trường

Để tìm tệp có nhãn cụ thể, hãy sử dụng cụm từ tìm kiếm labels có mã nhãn cụ thể.

Cách tìm tệp đã áp dụng nhãn cụ thể:

'labels/LABEL_ID' in labels

Cách tìm tệp chưa áp dụng nhãn cụ thể:

not 'labels/LABEL_ID' in labels

Cách tìm tệp dựa trên giá trị trường nhãn cụ thể:

labels/LABEL_ID.FIELD_ID = 'VALUE'

Nếu thành công, nội dung phản hồi sẽ chứa tất cả các thực thể tệp khớp với truy vấn. Để biết thêm thông tin, hãy xem phần Tìm tệp có nhãn hoặc giá trị trường cụ thể.

Tìm kiếm trên các tập hợp văn bản

Theo mặc định, tập hợp mục user được đặt trên tham số truy vấn corpora khi bạn sử dụng phương thức list. Để tìm kiếm các tập hợp mục khác, chẳng hạn như các tập hợp được chia sẻ với domain, bạn phải đặt tham số corpora một cách rõ ràng.

Bạn có thể tìm kiếm nhiều tập hợp văn bản trong một truy vấn; tuy nhiên, nếu tập hợp văn bản kết hợp quá lớn, API có thể trả về kết quả không đầy đủ. Kiểm tra trường incompleteSearch trong nội dung phản hồi. Nếu trường này là true, thì một số tài liệu đã bị bỏ qua. Để giải quyết vấn đề này, hãy thu hẹp corpora để sử dụng user hoặc drive.

Khi sử dụng tham số truy vấn orderBy trên phương thức list, hãy tránh sử dụng khoá createdTime cho các truy vấn trên các tập hợp mục lớn vì khoá này yêu cầu xử lý bổ sung và có thể dẫn đến thời gian chờ hoặc các vấn đề khác. Đối với việc sắp xếp liên quan đến thời gian trên các tập hợp mục lớn, bạn có thể sử dụng modifiedTime vì khoá này được tối ưu hoá để xử lý các truy vấn này. Ví dụ: đặt orderBy thành modifiedTime (hoặc modifiedTime desc).

Nếu bạn bỏ qua tham số truy vấn orderBy, sẽ không có thứ tự sắp xếp mặc định và các mục sẽ được trả về một cách tuỳ ý.