通过更少的 Java API 调用来映射 Google 云端硬盘内容的有效方法

问题描述 投票:0回答:1

大家好,我有一个代码,用于列出共享驱动器中存在的文件(以便稍后下载并创建相同的文件夹路径) 目前我正在做这样的事情:

  HashMap<String, Strin> foldersPathToID = new HashMap<>();

//searching all folders first saving their IDs 
searchAllFoldersRecursive(folderName.trim(), driveId, foldersPathToID);
  //then listing files in all folders
    HashMap<String, List<File>> pathFile = new HashMap<>();
    for (Entry<String, String> pathFolder : foldersPathToID.entrySet()) {
        List<File> result = search(Type.FILE, pathFolder.getValue());
        if (result.size() > 0) {
            String targetPathFolder = pathFolder.getKey().trim();
            pathFile.putIfAbsent(targetPathFolder, new ArrayList<>());
            for (File file : result) {
                pathFile.get(targetPathFolder).add(file);
            }
        }
    }

递归方法在哪里:

private static void searchAllFoldersRecursive(String nameFold, String id, HashMap<String, String> map) throws IOException, RefreshTokenException {   
 map.putIfAbsent(nameFold, id);
    List<File> result;

    result = search(Type.FOLDER, id);

    // dig deeper
    if (result.size() > 0) {
        for (File folder : result) {
            searchAllFoldersRecursive(nameFold + java.io.File.separator + normalizeName(folder.getName()),
                    folder.getId(), map);
        }
    }
} 

搜索功能是:

    private static List<com.google.api.services.drive.model.File> search(Type type, String folderId)
            throws IOException, RefreshTokenException {
        String nextPageToken = "go";
        List<File> driveFolders = new ArrayList<>();
        com.google.api.services.drive.Drive.Files.List request = service.files()
                .list()
                .setQ("'" + folderId
                        + "' in parents and mimeType" + (type == Type.FOLDER ? "=" : "!=")
                        + "'application/vnd.google-apps.folder' and trashed = false")
                .setPageSize(100).setFields("nextPageToken, files(id, name)");

        while (nextPageToken != null && nextPageToken.length() > 0) {
            try {
                FileList result = request.execute();
                driveFolders.addAll(result.getFiles());
                nextPageToken = result.getNextPageToken();
                request.setPageToken(nextPageToken);
                return driveFolders;
            } catch (TokenResponseException tokenError) {
                if (tokenError.getDetails().getError().equalsIgnoreCase("invalid_grant")) {
                    log.err("Token no more valid removing it Please retry");
                    java.io.File cred = new java.io.File("./tokens/StoredCredential");
                    if (cred.exists()) {
                        cred.delete();
                    }
                    throw new RefreshTokenException("Creds invalid will retry re allow for the token");
                }
                log.err("Error while geting response with token for folder id : " + folderId, tokenError);
                nextPageToken = null;
            } catch (Exception e) {
                log.err("Error while reading folder id : " + folderId, e);
                nextPageToken = null;
            }

        }
        return new ArrayList<>();
    }

我确信有一种方法可以通过很少的 api 调用(甚至可能是一个调用?)对每个文件(使用文件夹树路径)进行正确的映射,因为在我的版本中,我花了很多时间进行调用

service.files().list().setQ("'" + folderId+ "' in parents and mimeType" + (type == Type.FOLDER ? "=" : "!=") + "'application/vnd.google-apps.folder' and trashed = false").setPageSize(100).setFields("nextPageToken, files(id, name)");

每个子文件夹至少一次......并且递归搜索所有内容需要很长时间。最后,映射比下载本身花费的时间更多......

我搜索了文档,也在此处搜索,但没有找到任何内容来列出具有一个库的所有驱动器调用任何想法?

我想使用专用的 java API 来获取共享 GoogleDrive 中的所有文件及其相对路径,但调用次数尽可能少。

提前感谢您的时间和答复

java google-drive-api flysystem-google-drive
1个回答
0
投票

我建议您使用高效的数据结构和逻辑来构建文件夹树并将文件映射到其路径,如下所示

private static void mapDriveContent(String driveId) throws IOException {
    // HashMap to store folder ID to path mapping
    HashMap<String, String> idToPath = new HashMap<>();
    // HashMap to store files based on their paths
    HashMap<String, List<File>> pathToFile = new HashMap<>();

    // Fetch all files and folders in the drive
    List<File> allFiles = fetchAllFiles(driveId);

    // Build folder path mapping and organize files
    for (File file : allFiles) {
        String parentId = (file.getParents() != null && !file.getParents().isEmpty()) ? file.getParents().get(0) : null;
        String path = buildPath(file, parentId, idToPath);

        if (file.getMimeType().equals("application/vnd.google-apps.folder")) {
            idToPath.put(file.getId(), path);
        } else {
            pathToFile.computeIfAbsent(path, k -> new ArrayList<>()).add(file);
        }
    }

    // Now, pathToFile contains the mapping of paths to files
    // Your logic to handle these files goes here
}

private static List<File> fetchAllFiles(String driveId) throws IOException {
    // Implement fetching all files and folders here
    // Make sure to handle pagination if necessary
    // ...
}

private static String buildPath(File file, String parentId, HashMap<String, String> idToPath) {
    // Build the file path based on its parent ID and the idToPath mapping
    // ...
}


© www.soinside.com 2019 - 2024. All rights reserved.