Wes Neal
Wes Neal

Reputation: 23

How do I create a folder in Team Drive?

this is my first time submitting a question, so please help me if I could ask this better.

I want to:

I believe these resources tell me how to create the Team Drive folder:

Plan A: Create a folder using GAS. After some research, it’s my understanding that plain GAS cannot create a folder in Team Drive yet.

[18-03-15 14:55:23:674 EDT] Execution failed: Cannot use this operation on a Team Drive item. (line 139, file "utils") [1.618 seconds total runtime]

//The folder with the current name doesn't exist - create it in the parent folder
var newFolder = DriveApp.createFolder(nextFolderName);
currFolder.addFolder(newFolder);

If I’m wrong and there is a simple way to make the addFolder() code work with Team Drive, then that would be a win.

Update 1: You can create a folder in Team Drive with plain GAS. It is folder moving that is restricted. This works:

//The folder with the current name doesn't exist - create it in the parent folder
var newFolder = currFolder.createFolder(nextFolderName);

So Plan B: Now, I’m trying to create the folder using Google Drive REST API v3. However, I’m only getting an Untitled file in my personal drive when I run my code, even though TEAM_ROOT_PATH_FOLDER_ID is in a Team Drive. I think my problem is getting the right information to UrlFetchApp.fetch. It’s like the request body isn’t being read.

References:

Here’s my code for creating the folder using Google Apps Script and the Drive REST API:

var TEAM_ROOT_PATH_FOLDER_ID = "diPcXqabvgpX4tcZJZ-ms2Wg0bXf1Fem"; //TODO fill in based on parent folder

function test() {
  createTeamDriveFolder(TEAM_ROOT_PATH_FOLDER_ID);
}


function createTeamDriveFolder(parentFolderId) {

  //BUILD THE URL
  var baseUrl = "https://www.googleapis.com/upload/drive/v3/files/";

  var urlParams = { //TODO correct for this function (after you figure this out)
    supportTeamDrives: true
    //,alt: "json"
    ,uploadType: "media"
  };

  //CODE CREDIT: https://ctrlq.org/code/20514-list-team-drives-google-drive-apps-script
  var queryString = Object.keys(urlParams).map(function(p) {
    return [encodeURIComponent(p), encodeURIComponent(urlParams[p])].join("=");
  }).join("&");

  var apiUrlStr = baseUrl + "?" + queryString;


  //BUILD THE REQUEST - HEADERS AND BODY
  var token = ScriptApp.getOAuthToken();
  var requestBody = {
    mimeType: "application/vnd.google-apps.folder"
    ,name: "TeamDriveTestFolder"
    ,"parents": [parentFolderId]
  };

  var requestBodyStr = JSON.stringify(requestBody);
  Logger.log("requestBody: " + requestBodyStr);

  var requestParams = {
    method: "POST"
    ,contentType: "application/json"
    ,contentLength: requestBodyStr.length
    ,headers: {"Authorization": "Bearer " + token}
    ,payload: requestBodyStr
  };

  var response = UrlFetchApp.fetch(apiUrlStr, requestParams);

  Logger.log(response.getResponseCode());
  Logger.log(response.getContentText());
}

However, I can get a folder to appear in my personal drive (still wrong) when I run the REST call through the API test:

supportsTeamDrives > true

WORKS (TeamDriveTestFolder folder created in personal drive root):

{
  "mimeType": "application/vnd.google-apps.folder",
  "name": "TeamDriveTestFolder"
}

FAILS (404):

{
  "mimeType": "application/vnd.google-apps.folder",
  "name": "TeamDriveTestFolder",
  "parents": ["diPcXqabvgpX4tcZJZ-ms2Wg0bXf1Fem"]
}

I appreciate any assistance in cracking this Team folder creation.

Upvotes: 2

Views: 5478

Answers (3)

Ian Thomaz
Ian Thomaz

Reputation: 131

The MakeSubfolder is an amazing solution. Thinking about changing it to be a global alternative to new rootFolders as well.

If there's no parentFolder indicated just make it on Root.

Also it's amazing that works well with Drive and SharedDrive.

tnks a lot.

Upvotes: 1

Darpan Sanghavi
Darpan Sanghavi

Reputation: 1413

For your 3rd point "Nested in an existing team drive folder", you can directly use GAS. Following is the code snippet,

var parentFolder=DriveApp.getFolderById('folderId');
var newFolder=parentFolder.createFolder('name'); //replace name with Folder name.

Here you need to pass parent folder ID in folderId field. You can find this FolderID in the URL from Team Drive. In the below image '0AFmY7fi4434bUk9PVA' is the FolderID. enter image description here

Upvotes: 4

tehhowch
tehhowch

Reputation: 9872

Using the Drive advanced service (V2 API reference), it is fairly straightforward to create a folder, even in a Team Drive:

function getNewRootLevelFolderInTeamDrive(newTitle) {
  if(!newTitle) throw new TypeError("Missing argument for new folder's title");

  // Assumes you are working in the first Team Drive.
  var td = Drive.Teamdrives.list().items[0];
  var params = {
    supportsTeamDrives: true,
    includeTeamDriveItems: true,
  };
  // Making the folder uses Drive.Files.insert(). To create a folder, use the folder
  // MimeType, and ensure the resource is otherwise appropriately specified. You can
  // pass content, but it will be discarded, so just use `null` for the mediaBody / Blob.
  var metadata = {
    parents: [td],
    mimeType: MimeType.FOLDER,
    title: newTitle,
  };
  return Drive.Files.insert(metadata, null, params);
}

While the above method creates (and returns) a folder, it forces that folder to be a root-level folder in the first Team Drive. This is a pretty flimsy "force" though, as we can generalize the new folder to be the child of any given folder:

function makeSubFolder(parentId, title) {
  if(!parentId) throw new TypeError("Expected a string ID to be passed, identifying the parent folder in which a folder will be created.");
  if(!title) title = "Random Folder Title";

  var params = {
    supportsTeamDrives: true,
    includeTeamDriveItems: true,
    corpora: /* Review the Drive API documentation on corpora and choose the applicable option. */
  };
  var metadata = {
    parents:[],
    mimeType: MimeType.FOLDER,
    title: title,
  };
  // Get the parent folder. Because we explicitly allow team drive items, and
  // declare support for team drives, team drive folders can be used.
  var folder = Drive.Files.get(parentId, params);
  if(folder.mimeType !== MimeType.FOLDER)
    throw new TypeError("Input parent folder ID is a file of type='" + file.mimeType + "'. Folders must be type='" + MimeType.FOLDER + "'.");

  // Make the new folder in the parent folder.
  metadata.parents.push(folder);
  return Drive.Files.insert(metadata, null, params);
}

An example function using them both:

function foo() {
  var rootTDFolder = getNewRootLevelFolderInTeamDrive("stack_overflown");
  var folder = makeSubFolder(rootTDFolder.id, "a subfolder of 'stack_overflown'");
  console.log(rootTDFolder);
  console.log(folder);
}

Upvotes: 2

Related Questions