Skip to content Skip to sidebar Skip to footer

Create A Tree Directory Structure In Google Drive With Javascript

I am trying to build a simple directory tree with the Google Drive Javascript API. I suppose I should check for the folder existence and create it then add eventually its children.

Solution 1:

In this case I found the new asynchronous javascript syntax easier to understand.

Approach

You are running the function checkPhrFolder synchronously, while the other two functions, whose depend on the asynchronous api call, are waiting the promise to resolve in order to return a value. This will cause phr to be undefined when you evaluate it in the synchronous checkPhrFolder execution.

Basically for this to work you should chain your promises resolution in order to use their return values correctly. The new javascript syntax although enables you to write asynchronous functions with fewer lines of code. With the keywords async and await you can control the promises resolution flow, and basically wait the asynchronous function to return before making the proper assignment.

Example

asyncfunctioncreateFolder(name, parent) {
    if (!parent) parent = 'root';
    var fileMetadata = {
        'name': name,
        'mimeType': 'application/vnd.google-apps.folder',
        'parent': parent
    };
    const res = await gapi.client.drive.files.create({
        'resource': fileMetadata,
        'fields': 'id'
    });
    return res.result['id'];
}

asyncfunctiongetFolder(name, parent) {
    if (!parent) parent = 'root';
    const res = await gapi.client.drive.files.list({
        'pageSize': 1,
        'fields': "nextPageToken, files(id, name, mimeType, parents)",
        'q': "mimeType='application/vnd.google-apps.folder' \
                    and '" + parent + "' in parents \
                    and name = '" + name + "'"
    });
    return res.result.files.length > 0 ? res.result.files[0]['id'] : null;
}

asyncfunctioncheckPhrFolder() {
  var phr = awaitgetFolder('Personal Health Record');
  console.log('get folder: '+phr);
  if (!phr) {
      console.log('creating ...');
      phr = createFolder('Personal Health Record');
  }
}

In this way your checPhrFolder function will be almost as easy to read as before. When you will use the checkPhrFolder function in a synchronous context you will be able to wrap its return value in the same then/catch statement.

Reference

Async/Await

Solution 2:

I used the traditional way to build my dirs populator this way below:

var phrFolderManager = {
        currentName: null,
        currentParent: null,
        folders: {
            '/PersonalHealthRecord': null,
            '/PersonalHealthRecord/Some': null,
            '/PersonalHealthRecord/Dirs': null,
            '/PersonalHealthRecord/ForMe': null
        },
        addFolder: function (name, id) {
            this.folders[name] = id;
        },
        getFolderId: function (name) {
            returnthis.folders[name];
        },
        refresh: function (forced) {
            console.log('next step ' + forced + ' ...');
            console.log(this.folders);
            // find the next null in our folder listfor (k inthis.folders) {
                this.currentName = k;
                if (!this.folders[k]) {
                    var parts = k.split('/');
                    if (parts.length == 2) {
                        // this is our base dir inside rootif (forced) {
                            this.createFolder(parts[1], 'root');
                        } else {
                            this.getFolder(parts[1], 'root');
                        }
                    } else {
                        var parent = parts.slice(0, -1).join('/');
                        var name = parts[parts.length - 1];
                        var parent_id = this.folders[parent];
                        if (forced) {
                            this.createFolder(name, parent_id);
                        } else {
                            this.getFolder(name, parent_id);
                        }
                    }
                    break;
                } else {
                    console.log('... defined as ' + this.folders[k]);
                }
            }
        },
        getFolder: function (name, parent) {
            //M.toast({html: 'check da pasta '+name,classes: 'rounded'});if (!parent) parent = 'root';
            this.currentParent = parent;
            console.log('getFolder ' + name + ' ' + parent);
            var res = gapi.client.drive.files.list({
                'pageSize': 1,
                'fields': "files(id, name, mimeType, parents)",
                'q': "mimeType='application/vnd.google-apps.folder' \
                        and '" + parent + "' in parents \
                        and name = '" + name + "'"
            }).then(
                function (res) {
                    console.log(res);
                    if (res.result.files.length > 0) {
                        this.folders[this.currentName] = res.result.files[0]['id'];
                        this.refresh(false);
                    } else {
                        this.refresh(true);
                    }
                },
                function (err) {
                    console.log('error in getFolder: ' + err)
                },
                this
            );
        },
        createFolder: function (name, parent) {
            M.toast({
                html: 'criando pasta ' + name,
                classes: 'rounded'
            });
            if (!parent) parent = 'root';
            console.log('createFolder ' + name + ' ' + parent);
            var fileMetadata = {
                'name': name,
                'mimeType': 'application/vnd.google-apps.folder',
                'parents': [parent]
            };
            gapi.client.drive.files.create({
                'resource': fileMetadata,
                'fields': 'id'
            }).then(
                function (res) {
                    console.log(res);
                    this.folders[this.currentName] = res.result['id'];
                    this.refresh();
                },
                function (err) {
                    alert('Problem creating ' + this.currentName + ' PersonalHealthRecord structure');
                },
                this
            );
        }
    };

Solution 3:

With a little tweaking, @Alessandro's solution worked for me:

  • I reversed the order of the methods just for readability.
  • I incorporated a FOR loop because my file structure will go many folders deep. The loops is through an array of strings containing the folder names in the file path.
  • I noticed that (!parent) wasn't returning properly because it was "undefined", not "null". Also, expecting "null" when the existing folder wasn't found was vital, so I defaulted parentId to "root" since I know my first folder will always be at root
  • variable newFolderId holds the value of the found/created folder, and is passed onto the parentId for the next iteration of the FOR loop
  • Finally, I updated "'parent': parent" to be "'parents' : [parent]". That "s" and those brackets seem necessary, otherwise every created folder is placed at root.
asyncfunctionbuildFilePath() {

            console.log("buildFilePath()");

            var parentId = "root";

            for (let i = 0; i < filePath.length; i++)  {
                var folderName = filePath[i];

                newFolderId = awaitgetFolder(folderName, parentId);
                console.log(folderName + " id is " + newFolderId + ", parentId is " + parentId);
                if (newFolderId == null) {
                    newFolderId = awaitcreateFolder(folderName,parentId);
                    console.log ("created new folder " + folderName + " with Id " + parentId);
                } else {
                    // parentId = newParentId;console.log (folderName + " already exist, move on to next.");
                }
                parentId = newFolderId;
            }
        }
        asyncfunctiongetFolder(name, parent) {

            const res = await gapi.client.drive.files.list({
                'pageSize': 1,
                'fields': "nextPageToken, files(id, name, mimeType, parents)",
                'q': "mimeType='application/vnd.google-apps.folder' \
                            and '" + parent + "' in parents \
                            and name = '" + name + "' \
                            and trashed = false"
            });
            return res.result.files.length > 0 ? res.result.files[0]['id'] : null;
        }
        asyncfunctioncreateFolder(name, parent) {

            if (!parent) parent = 'root';

            var fileMetadata = {
                'name': name,
                'mimeType': 'application/vnd.google-apps.folder',
                'parents': [parent]
            };
            const res = await gapi.client.drive.files.create({
                'resource': fileMetadata,
                'fields': 'id'
            });
            return res.result['id'];
        }

Post a Comment for "Create A Tree Directory Structure In Google Drive With Javascript"