28

dear all

I'm trying to find a list of documents by "full path". And after reading the API reference, it seems to be a complex task. Assume my path is something like /path0/path1/path2/...

  1. List children of root folder and find all children with name equals "path0" and put them to a list "result0"
  2. Find all children of items in "result0" with name equals "path1" and put them to a list "result1"
  3. Find all children of items in "result1" with name equals "path2" and ...

Above approach seems very low efficient cause it needs multiple interactions between my application and Drive. I understand Google Drive allows multiple files share the same file name even in the same folder. It will be handy if I can do something like:

listDocByFullPath("path0/path1/path2")

Is this possible with current version of Google Drive SDK? If it's not there yet, I was wondering if there is a simpler way than what I listed here.

BTW, as my application is purely a back-end service, it's not possible to use file picker provided by Google.

Cheers.

James Gan
  • 6,988
  • 4
  • 28
  • 36
  • 1
    Did you ever find a solution? I'm facing the exact same problem. – VVV Jan 15 '16 at 16:27
  • it should be easy now, check out the sample app which provides all solutions https://github.com/gsuitedevs/android-samples/tree/master/drive – thanhbinh84 Jul 10 '18 at 02:45

4 Answers4

20

Unlike conventional file systems, a file could be under multiple folders on Drive. Folders are pretty much similar what labels are. Therefore, conventional paths dont always work within our abstraction. I'd suggest you to follow the logic below:

  1. List files with q = 'root' in parents and title = 'path0' and mimeType = 'application/vnd.google-apps.folder' and pick the first result.
  2. If there is a matching result, get the folder's id and perform another listing with '<id of path0>' in parents and title = 'path1' and mimeType='application/vnd.google-apps.folder' and pick the first result.
  3. Keep going until you reach to your target folder.
Burcu Dogan
  • 9,153
  • 4
  • 34
  • 34
  • 9
    I would like to see a service to resolve the destination id for me. – peter Jun 25 '13 at 09:17
  • 7
    Hi, Burcu Thanks for your reply. This exactly what I'm doing now. It seems Ok at the moment. Though I got worried about future performance. It seems interactions between my application and Drive API increase linearly as depth of directory increases. The API I proposed can really simplify things here. Cheers. – James Gan Jun 25 '13 at 10:42
  • 1
    @burcu-dogan is there any chance for a functionallity like this to get included to the api in the future? Performance should increase when the iteration is done on Google Drive API side. – FFirmenich Nov 24 '20 at 12:26
  • 1
    "Unlike conventional file systems, a file could be under multiple folders on Drive." Lots of filesystems have symlinks and junctions. I don't think that is any excuse for not allowing pathname resolution to identify a file. There could be 20 paths to access a file, if the one I have works, then that's all I need to care about. It's a huge oversight by Google not to include basic pathname resolution for common-case and rapid development purposes. – jstine Dec 05 '22 at 21:33
7

The biggest problem is that a path does not uniquely identify the file or folder! For example, in the web UI, you can make 2 folders with the same name as children of the same folder. i.e. you can make a tree that looks like: root |-somefolder |-somefolder

Rehan
  • 1,299
  • 2
  • 16
  • 19
1
  1. Search / list with the param q set to name= and include fields param with "files(mimeType,id,name,parents)"
  2. If there is only one search result, return this file
  3. Else if there are multiple files, get the ID in parent and use file's get API with that ID and check if the name matches the last fragment in the path. If only one of the parent Ids match select that option else pick the matching parents and get to check the next parent element in the path

Essentially check bottom up

arunram
  • 623
  • 7
  • 11
0

@Barcu Dogan is correct,, that's the only way to find full path, here is the implementation:

//BeanConfig.java
   @Bean
    @Scope(ConfigurableBeanFactory.SCOPE_SINGLETON)
    public Drive drive() throws GeneralSecurityException, IOException {
        Drive drive = new Drive.Builder(GoogleNetHttpTransport.newTrustedTransport(), JSON_FACTORY, getCredentials())
                .setApplicationName(APPLICATION_NAME)
                .build();

        return drive;
    }

    private static HttpRequestInitializer getCredentials() throws IOException {
        // Load client credentials from path
        GoogleCredentials credential = GoogleCredentials.fromStream(new FileInputStream(CREDENTIALS_FILE_PATH))
                .createScoped(DriveScopes.all());

        return new HttpCredentialsAdapter(credential);
    }


//FileHelper.java
//pass folderId or fileId
public String getCompletePath(Drive drive, String folderId) {
        String path = "";
        try {
            File files = drive.files()
                    .get(folderId).setFields("id,name,parents")
                    .execute();
            return recursivePath(drive, files, path);
        } catch (IOException e) {
            e.printStackTrace();
        }

        return path;
    }

public String recursivePath(Drive drive, File currentFolder, String path) throws IOException {
        if (currentFolder == null || currentFolder.getParents() == null || currentFolder.getParents().isEmpty())
            return path;
        if (!path.equalsIgnoreCase("")) {
            path = currentFolder.getName() + "/" + path;
        } else {
            path = currentFolder.getName();
        }
        File parentFolder = drive.files().get(currentFolder.getParents().get(0)).setFields("id,name,parents").execute();
        return recursivePath(drive, parentFolder, path);
    }
Dave Ranjan
  • 2,966
  • 24
  • 55