google drive api create sub folders - google-drive-api

I need to create sub folders in google drive using google drive api added using nuget package in console application.
I can get the folder id of root folder. Can get children of rot folder, can also upload file in root folder. Only problem is creation of sub folders in folders.
for (int i = 1; i < array.Count(); i++)
{
var subfoldername = new Google.Apis.Drive.v2.Data.File { Title = array[i], MimeType = "application/vnd.google-apps.folder" };
ChildrenResource.ListRequest request = service.Children.List(rootfolderid);
ChildList children = request.Execute();
if (children.Items.Count > 0)
{
foreach (ChildReference c in children.Items)
{
Google.Apis.Drive.v2.Data.File file = service.Files.Get(c.Id).Execute();
if (file.MimeType == "application/vnd.google-apps.folder")
{
List<GoogleDriveFile> googledrive = new List<GoogleDriveFile>();
googledrive.Add(new GoogleDriveFile
{
OriginalFilename = file.OriginalFilename
});
}
}
}
else
{
// here need to add sub folder in folder, but this line adds folder at root
var result = service.Files.Insert(foldername).Execute();
}

Here is the way i do, when creating a sub folder in google drive it must need a parents. So before execute the string q, we need to search for the parent root id
string findRootId = "mimeType = 'application/vnd.google-apps.folder' and title ='" + RootFolder + "' and trashed = false";
IList<File> _RootId = GoogleDriveHelper.GetFiles(service, findRootId);
if (_RootId.Count == 0) {
_RootId.Add(GoogleDriveHelper.createDirectory(service, RootFolder, "", "root"));
Console.WriteLine("Root folder {0} was created.", RootFolder);
}
var id = _RootId[0].Id;
string Q = "mimeType = 'application/vnd.google-apps.folder' and '" + id + "' in parents and title ='" + GoogleDriveFolderName + "' and trashed = false";

You must add the property parents while creating a Folder.
parents[]
Collection of parent folders which contain this file.
Setting this field will put the file in all of the provided folders. On insert, if no folders are provided, the file will be placed in the default root folder.
Sample Code:
function createSubFolder() {
var body = new Object();
body.title = 'SubFolder';
body.parents = [{'id':'0B5xvxYkWPFpCUjJtZVZiMWNBQlE'}];
body.mimeType = "application/vnd.google-apps.folder";
console.log(body)
var request = gapi.client.request({
'path': '/drive/v2/files',
'method': 'POST',
'body': JSON.stringify(body)
});
request.execute(function(resp) { console.log(resp); });
}
I'm using Drive v2 in JavaScript
Hope this helps

Related

How to create a list of all folders in a shared goggle drive folder

I'm trying to create a listing of all my google drive folders and I have the following script and a link to the question where I got the script from. I'm just not sure how to implement it. I put the Drive ID in line 6 and then ran it and got this error; Can anyone tell me where I'm going wrong?
List every file and folder of a shared drive in a spreadsheet with Apps Script
11:08:37 AM Error
ReferenceError: gobj is not defined
getFoldersInASharedFolder # Folder Listing.gs:12
This is the script
function getFoldersInASharedFolder() {
let tr = [];
let token = '';
let page = 0;
do {
let r = Drive.Files.list({ corpora: 'drive', includeItemsFromAllDrives: true, supportsTeamDrive: true, supportsAllDrives: true, driveId: "???", pageToken: token,q: "mimeType = 'application/vnd.google-apps.folder'" });
let obj = JSON.parse(r);
tr.push(obj)
token = obj.nextPageToken
} while (token != null)
let folder = DriveApp.getFolderById(gobj.globals.testfolderid);
folder.createFile(`SharedDriveList ${Utilities.formatDate(new Date(), Session.getScriptTimeZone(), "MM/dd/yyyy HH:mm:ss")}`, JSON.stringify(tr), MimeType.PLAIN_TEXT);
let html = '<style>td,th{border:1px solid black;font-size: 16px;}</style><table><tr><th>Title</th><th>Id</th><th>Path</th></tr>';
tr.forEach((o, i) => {
o.items.forEach(item => {
if (item.mimeType = "application/vnd.google-apps.folder") {
html += `<tr><td>${item.title}</td><td>${item.id}</td><td>${getPathAllDrivesFromId(item.id)}</td></tr>`;
}
})
});
html += '</table><input type="button" value="exit" onclick="google.script.host.close()" />';
SpreadsheetApp.getUi().showModelessDialog(HtmlService.createHtmlOutput(html).setHeight(500).setWidth(1200), `Folders in: ${JSON.parse(Drive.Drives.get("driveid")).name}`);
}
The error message occurs because
let folder = DriveApp.getFolderById(gobj.globals.testfolderid);
use the a nested property of gobj as parameter but gobj was not declared.
You can fix this error either by properly declaring gobj or by replacing gobj.globals.testfolderid by the folder id (properly set as a string).
The comments explain how to use this function
function getFoldersInASharedFolder() {
const sharedriveid = "";//add the shared drive id here
const storagefilefolderid = ""; //this where I was storing the response which I used when I was first building the script. It's not necessary to do this if you don't wish to. You can just comment that code out of the script
let tr = [];
let token = '';
let page = 0;
do {
let r = Drive.Files.list({ corpora: 'drive', includeItemsFromAllDrives: true, supportsTeamDrive: true, supportsAllDrives: true, driveId: sharedriveid, pageToken: token,q: "mimeType = 'application/vnd.google-apps.folder'" });//drive id for the shared drive that you wish all of the folders from
let obj = JSON.parse(r);
tr.push(obj)
token = obj.nextPageToken
} while (token != null)
let folder = DriveApp.getFolderById(storagefilefolderid);//the folder id for the file that stores the results
folder.createFile(`SharedDriveList ${Utilities.formatDate(new Date(), Session.getScriptTimeZone(), "MM/dd/yyyy HH:mm:ss")}`, JSON.stringify(tr), MimeType.PLAIN_TEXT);
let html = '<style>td,th{border:1px solid black;font-size: 16px;}</style><table><tr><th>Title</th><th>Id</th><th>Path</th></tr>';
tr.forEach((o, i) => {
o.items.forEach(item => {
if (item.mimeType = "application/vnd.google-apps.folder") {
html += `<tr><td>${item.title}</td><td>${item.id}</td><td>${getPathAllDrivesFromId(item.id)}</td></tr>`;
}
})
});
html += '</table><input type="button" value="exit" onclick="google.script.host.close()" />';
SpreadsheetApp.getUi().showModelessDialog(HtmlService.createHtmlOutput(html).setHeight(500).setWidth(1200), `Folders in: ${JSON.parse(Drive.Drives.get(sharedrivedid)).name}`);
}

Able to create Google Docs but couldn't create Google Sheets

I am making a feature in my Java backend to create a Google Sheet.
Now in that backend, it already has a function to create Google Docs and it is working well. Following is the function to create a Google Doc.
public String createFileFromHtml(Project project, String html) throws DocumentGatewayException {
// Determine the google drive ID for the given areaId
String areaId =
Strings.isNullOrEmpty(project.getAreaId()) ? Constants.TEST_AREA : project.getAreaId();
String areaGoogleDriveId = null;
try {
if (areaIdToGoogleDriveIdMap.isEmpty() || !areaIdToGoogleDriveIdMap.containsKey(areaId)) {
String pageToken = null;
do {
String query = "'" + ERD_GOOGLE_DRIVE_ID + "' in parents";
query += " and mimeType = '" + FOLDER_MIME_TYPE + "'";
query += "and trashed = false";
FileList result =
drive
.files()
.list()
.setQ(query)
.setPageToken(pageToken)
.setFields("nextPageToken, files(id, name)")
.execute();
for (File file : result.getFiles()) {
areaIdToGoogleDriveIdMap.put(file.getName(), file.getId());
}
pageToken = result.getNextPageToken();
} while (pageToken != null);
}
} catch (IOException e) {
throw new DocumentGatewayException(e);
}
areaGoogleDriveId = areaIdToGoogleDriveIdMap.get(areaId);
Preconditions.checkArgument(
!Strings.isNullOrEmpty(areaGoogleDriveId), areaId + " needs to have a google drive folder");
// Generate metadata to be used to create the file using the google drive ID above.
File fileMetadata = new File();
fileMetadata.setName(project.getTitle());
fileMetadata.setMimeType("application/vnd.google-apps.document");
fileMetadata.setParents(Collections.singletonList(areaGoogleDriveId));
try {
// Create file.
File file =
drive
.files()
.create(
fileMetadata,
new ByteArrayContent("text/html", html.getBytes(StandardCharsets.UTF_8)))
.setFields("id")
.execute();
// Make all authors writers
if (!project.getAuthorIds().isEmpty()) {
for (String authorId : project.getAuthorIds()) {
processor.setWritter(project.getUuid(), file.getId(), authorId, 0);
}
// Set owner
String authorId = EmailUtils.AuthorNameToEmail(project.getAuthorIds().get(0));
processor.setOwner(project.getUuid(), file.getId(), authorId, 0);
}
// Set commenter
processor.setCommenter(project.getUuid(), file.getId(), 0);
return file.getId();
} catch (IOException e) {
logger.error(
"Error creating document", KeyValue.string("project_uuid", project.getUuid()), e);
throw new DocumentGatewayException(e);
}
}
I wanted to create a Google Sheet instead. So I tried changing application/vnd.google-apps.document to application/vnd.google-apps.spreadsheet. But after this change, it was still creating Google Doc instead of Google Sheet.
So anyones knows why? I just need to create a Google Sheet.
Google Drive API version: google-api-services-drive-v3-rev130-1.25.0
Thanks.

Retrieving files from a shared folder using Drive api V3,

I have read/write permissions to a shared folder with another Google user.
I want to list all the files (in all the folders) in that shared folder link using drive V3 API.
What is the best way to do this?
The solution currently employed is pretty slow in performance if the number of folders inside shared folders is large.
My Current solution:
1 - Finding all the folders in shared link
2 - Finding all files whose parent is folder
private void getFolderHierarchy(File Res, DriveService driveService, string localPath, string editorName, string projectName)
{
if (Res.MimeType == "application/vnd.google-apps.folder")
{
m_parent += Res.Name + #"\";
foreach (var res in ResourceFromFolder(driveService, Res.Id).ToList())
getFolderHierarchy(res, driveService, localPath, editorName, projectName);
m_parent = m_parent.Remove(m_parent.Length - Res.Name.Length - 1);
}
else if (Res.MimeType == "image/jpeg" || Res.MimeType == "image/png")
{
{
if (!m_DownloadedFromEditorFileId.Contains(Res.Id))
{
m_DownloadedGoogleFileId.Add(Res.Name);
m_parent = m_parent.Remove(m_parent.Length - Res.Name.Length);
}
}
}
}
public List<File> ResourceFromFolder(DriveService service, string folderId)
{
var request = service.Files.List();
request.PageSize = 100;
request.Q = "'" + folderId + "'" + " in parents and trashed=false";
request.Fields = "files(modifiedTime,id,parents,name,webContentLink,mimeType)";
List<File> TList = new List<File>();
do
{
var children = request.Execute();
foreach (var child in children.Files)
{
System.Threading.Thread.Sleep(10);
TList.Add(service.Files.Get(child.Id).Execute());
}
request.PageToken = children.NextPageToken;
} while (!String.IsNullOrEmpty(request.PageToken));
return TList;
}
The second option would be the best way to get the files from a shared folder. As stated in this related SO post use files/list with a parent query.
GET https://www.googleapis.com/drive/v2/files?q='FOLDERID'+in+parents&key={YOUR_API_KEY}
The speed will depend of how large/many the files under the that shared folder.
Hope this helps.

script to read/write a file that is stored in a local "dropbox" folder or a local "google drive"

For the moment, the dropbox API allows a browser to access (read/write) all type of files in a dropbox folder on your local drive by script. The file path and name can be specified in the script. The script works on webpages that are stored on a local drive, but also works on webpages that are stored on a remote site when using Chrome.
Please see these jsfiddles with a primitive implementation to test writing and reading a text file in a local dropbox folder. The scripts are written in pure vanilla javascript code, and no not need a library.
Only a one-time access token is needed and no further authentication procedure.
This jsfiddle (click) demonstrates: Write text file to local dropbox folder
function WriteFile() {
var H = new Array(6);
H[0] = "Authorization";
H[1] = document.getElementById("bear").value;
H[2] = "Content-type";
H[3] = "application/octet-stream";
H[4] = "Dropbox-API-Arg";
H[5] = '{"path": "/' + document.getElementById("pana").value;
H[5] = H[5] + '","mode":{".tag":"overwrite"}}';
var X = new XMLHttpRequest();
X.onreadystatechange = acb;
X.open("POST", "https://content.dropboxapi.com/2/files/upload", true);
X.setRequestHeader(H[0], H[1]);
X.setRequestHeader(H[2], H[3]);
X.setRequestHeader(H[4], H[5]);
X.send(document.getElementById("myText").value);
document.getElementById("demo").innerHTML = "writing . . .";
}
function acb(A) {
var X = A.target;
var G = X.readyState;
if (G != 4) {
return 0;
}
document.getElementById("demo").innerHTML = "status: " + X.status;
}
This jsfiddle (click) demonstrates: Read text file from local dropbox folder
function ReadFile() {
document.getElementById("text").value = "";
var H = new Array(6);
H[0] = "User-Agent";
H[1] = "api-explorer-client";
H[2] = "Authorization";
H[3] = document.getElementById("bear").value;
H[4] = "Content-type";
H[5] = "application/json";
var X = new XMLHttpRequest();
X.onreadystatechange = acb;
X.open("POST", "https://api.dropboxapi.com/2/sharing/create_shared_link", true);
X.setRequestHeader(H[0], H[1]);
X.setRequestHeader(H[2], H[3]);
X.setRequestHeader(H[4], H[5]);
X.send('{"path": "/' + document.getElementById("pana").value + '"}');
document.getElementById("stat").innerHTML = "Reading . . .";
}
// async call back 1
function acb(A) {
var X = A.target;
if (X.readyState != 4) {
return 0; // when ready
}
var stat = X.status;
document.getElementById("stat").innerHTML = "status: " + stat;
if (stat != 200) {
document.getElementById("text").value = "NOT FOUND";
return 0; // error
}
var B = X.responseText;
var C = JSON.parse(B);
var D = C.url;
var E = D.split(".com");
var F = E[1];
var G = "https://dl.dropboxusercontent.com" + F;
document.getElementById("text").value = G;
X = new XMLHttpRequest();
X.onreadystatechange = acb2;
X.open("GET", G, true);
X.send(null);
}
// async callback 2
function acb2(A) {
var X = A.target;
if (X.readyState != 4) {
return 0; // when ready
}
var stat = X.status;
if (stat != 200) {
document.getElementById("text").value = "Can't Read the file";
return 0; // error
}
var B = X.responseText;
document.getElementById("text").value = B;
}
I tried to obtain the same functionality for files in a "google drive" on a local drive , using the "google drive API", but without success. Can someone achieve this, eventually using other cloud storage systems.

Google scripts, get a drive file url

I need my script to load the URL of a drive file to be added to a spreadsheet. For whatever reason 'File.getUrl()' returns null, but everything else seems to be working.
For example, 'File.getName()' works. So am I missing a permission or something?
Here is my code (abridged):
function loadURL(folderPath, name) {
var folder = loadFolder(folderPath);
// Find file
var files = folder.searchFiles('modifiedDate >= "' + getDate() + '" and title = "' + name + '"'),
file, found = 0;
for (; files.hasNext(); found++) {
file = files.next();
}
if (found == 1) {
/////////////////////////////////
// Here is 'getUrl'
/////////////////////////////////
var url = file.getUrl();
Logger.log("Loaded: " + url);
return url;
} else {
throw "Error loading file";
}
}
/**
* ** NOTE: THIS SEEMS TO BE WORKING FINE **
* Load a folder
* #param {string} url
* #return {Folder}
*/
function loadFolder(url) {
var folders = url.split('/'),
folder = DriveApp.getRootFolder();
Logger.log("Loading URL: " + url);
for (var key in folders) {
var fName = folders[key];
if (fName.length > 0) {
var fIt = folder.getFoldersByName(fName),
found = 0;
Logger.log(" -> " + fName);
for (; fIt.hasNext(); found++) {
folder = fIt.next();
}
if (found == 0) {
throw "Could not find the folder '" + fName + "'";
} else if (found > 1) {
throw "Found multiple matches to the folder '" + fName + "'";
}
}
}
return folder;
}
And the log if you're curious:
[14-02-26 19:56:15:980 EST] Loading URL: Work/PDF/
[14-02-26 19:56:15:981 EST] -> Work
[14-02-26 19:56:16:120 EST] -> PDF
[14-02-26 19:56:16:450 EST] Loaded: null
And if I change getUrl to getName it (kinda) works
[14-02-26 20:10:20:588 EST] Loading URL: Work/PDF/
[14-02-26 20:10:20:589 EST] -> Work
[14-02-26 20:10:20:727 EST] -> PDF
[14-02-26 20:10:21:058 EST] Loaded: Test
var url = DocsList.getFileById(fileId).getUrl();
Was recommended as a workaround by a poster on the issue thread that zig posted.
So, in your case, you'd use:
for (; files.hasNext(); found++) {
file = files.next();
}
if (found == 1) {
/////////////////////////////////
// Here is 'getUrl'
/////////////////////////////////
var fileId = file.getId();//new line added to getId of the file
//modified url line to reference doc by id
var url = DocsList.getFileById(fileId).getUrl();
Logger.log("Loaded: " + url);
return url;
} else {
throw "Error loading file";
}
I didn't get to test this right now because it's late and I'd have to build a the right structure to test it properly, but since you already have the structure change those two commented lines and let me know if that worked.
Using the id instead of the url works:
var url = "https://docs.google.com/document/d/" + file.getId() + "/";
Today started an issue with drive getUrl, google is aware of it and working on it.
Does work using docList or drive advanced services.