2
votes

DISCUSSION

Google Drive API v3: Create Folder

CLOUD DRIVE APIs COMPARISON

Other cloud drive APIs when creating a folder, including Box API and Dropbox API, both return a conflict error if a folder of the same name already exists in parent folder.

However, Google Drive API by default allows creating folders of the same name.

QUESTION

Is there a way to return conflict error if trying to create a folder of the same name within Google Drive parent folder?

If I take the approach using API to search for folder by name first, then create folder if not exists, then this could result in a possible race condition by a parallel process doing the same task in creating a unique folder by name.

EXAMPLE

Google Drive API create folder call in curl

curl "https://www.googleapis.com/drive/v3/files" \
--request POST \
--verbose \
--write-out 'HTTPSTATUS:%{http_code}' \
--silent \
--header "authorization: Bearer [** ACCESS TOKEN **]" \
--header "cache-control: no-cache" \
--header "content-type: application/json; charset=utf-8" \
--header "Accept: application/json" \
--data '{ \
    "mimeType":"application\/vnd.google-apps.folder", \
    "name": "[** FOLDER NAME **]", \
    "parents": ["root"] \
}'

Each call creates a new folder in Google Drive parent folder with unique folder id, however, same folder name. I wish to avoid this:

Success [HTTP status: 200]
{
  "kind": "drive#file",
  "id": "1mpy2-TVeZDTL8vZ6fKHTyoGoFHX-18EN",
  "name": "TEST",
  "mimeType": "application/vnd.google-apps.folder"
}
...
Success [HTTP status: 200]
{
  "kind": "drive#file",
  "id": "1iqYnEWOVFcWO3jWX1IgIv2wxtGVYruQX",
  "name": "TEST",
  "mimeType": "application/vnd.google-apps.folder"
}

I appreciate any assistance in getting a single call approach to either return conflict error or auto-renaming.

1
Jeff, were you able to find a single-call solution to this? If we had a way to hash a string to a valid Google item ID, then both workers would be able to use the same ID during their create requests and get the collision detection. But if Google is doing its own book-keeping on the IDs it generates, then such a hash function would seem unlikely...user3735178

1 Answers

2
votes
  • You want to return the conflict error, if the same folder name is existing when new folder is created in the specific folder.
  • You want to use this with the asynchronous process.
    • In this case, you don't want to create the duplicated folder name.
  • You want to achieve this by one API call with Drive API.

If my understanding is correct, how about this answer? Please think of this as just one of several possible answers.

Issue and workaround:

At Google Drive, all files and folders are managed by the unique ID. By this, the files and folders with the same name can be created in a folder. When Drive API is used, this uses the ID which is not the filename and folder name. So in order to achieve your goal with Drive API, it is required to search the folder name. And also, the exclusive processing is required to for prevent to be created the same folder name with the asynchronous process. By this, unfortunately, your goal cannot be achieved with only the simple curl command.

From above situation, in order to achieve your goal with only the simple curl command, I would like to use Web Apps as an API as a workaround. Web Apps is created by Google Apps Script and this can be used like an API. By this, I thought that your goal can be achieved by this workaround.

Usage:

In order to use this workaround, please do the following flow.

  1. Create new Google Apps Script project.

    1. Access to script.google.com. In this case, the login screen is shown. So so please login to Google. By this, the script editor is opened.
    2. When you access to script.google.com for the first time, you'll be redirected to a page that introduces Apps Script. At that time, please click Start Scripting to proceed to the script editor.
    3. Input the filename of GAS project at the top left.
  2. Copy and paste the following sample script. This is used as the script of server side.

    function doGet(e) {
      var lock = LockService.getScriptLock();
      if (lock.tryLock(10000)) {
        var parent, folder;
        if (e.parameter.parentId) {
          parent = DriveApp.getFolderById(e.parameter.parentId);
          folder = parent.getFoldersByName(e.parameter.folderName);
        } else {
          parent = DriveApp.getRootFolder();
          folder = DriveApp.getFoldersByName(e.parameter.folderName);
        }
        if (folder.hasNext()) {
          lock.releaseLock();
          var err = {error: "Same folder name is existing."};
          return ContentService.createTextOutput(JSON.stringify(err)).setMimeType(ContentService.MimeType.JSON);
        }
        var folderId = parent.createFolder(e.parameter.folderName).getId();
        lock.releaseLock();
        var msg = {message: "Done.", folderId: folderId};
        return ContentService.createTextOutput(JSON.stringify(msg)).setMimeType(ContentService.MimeType.JSON);
      }
    }
    
    • Unfortunately, Web Apps cannot manage the response code. In this case, the status code of 200 is returned even when an error occurs in the script. So I returned the response value as JSON object.
    • In this script, the process is run with the exclusive processing. By this, even when you run the request with the asynchronous process, the same folder name is not created.
  3. Deploy Web Apps.

    1. On the script editor, Open a dialog box by "Publish" -> "Deploy as web app".
    2. Select "Me" for "Execute the app as:".
    3. Select "Only myself" for "Who has access to the app:".
      • In this case, in order to access to Web Apps, it is required to use the access token.
      • If "Anyone, even anonymous" is used instead of "Only myself", the access token is not required to be used.
    4. Click "Deploy" button as new "Project version".
    5. Automatically open a dialog box of "Authorization required".
      1. Click "Review Permissions".
      2. Select own account.
      3. Click "Advanced" at "This app isn't verified".
      4. Click "Go to ### project name ###(unsafe)"
      5. Click "Allow" button.
    6. Click "OK".
    7. Copy the URL of Web Apps. It's like https://script.google.com/macros/s/###/exec.
      • When you modified the Google Apps Script, please redeploy as new version. By this, the modified script is reflected to Web Apps. Please be careful this.
      • I think that the developer mode can be also used because the access token is used. But in your case, I thought that the script of server side might be suitable that it is managed as the version. So I didn't propose to use the developer mode.
  4. Use the deoloyed Web Apps with the following curl command.

    curl -L \
      -H "Authorization: Bearer ###" \
      "https://script.google.com/macros/s/###/exec?parentId=###&folderName=###"
    
    • parentId and folderName are used as the query parameter.
    • When the same folder name of folderName is existing in the folder of parentId, {"error":"Same folder name is existing."} is returned.
    • When the same folder name of folderName is NOT existing in the folder of parentId, new folder is created and {"message":"Done.","folderId":"### folder ID of created folder ###"} is returned.

References:

If I misunderstood your question and this was not the direction you want, I apologize.