Google Drive API - How to make sub-folder into the Team Drive - google-drive-api

I'm developing small system using Google Drive API with JAVA,
I am wondering about the TeamDrive API among Google Drive APIs.
First of all, I created team drive folder,
Create Team Drive
public static void createTeamDrive(String accessToken) throws IOException {
long startTime = System.currentTimeMillis();
TeamDrive teamDriveMetadata = new TeamDrive();
teamDriveMetadata.setName("Team Drive API Test");
String requestId = UUID.randomUUID().toString();
TeamDrive teamDrive = getDriveService(accessToken).teamdrives().insert(requestId, teamDriveMetadata).execute();
System.out.println("[Create TeamDrive] execution time : " + (System.currentTimeMillis() - startTime));
}
and then I shared the user.
Share User
public static Permission ShareUser(String teamDriveFolderId, String googleMail, String accessToken) {
long startTime = System.currentTimeMillis();
Permission userPermission = new Permission().setRole("reader")
.setType("user").setEmailAddress(googleMail)
.setValue(googleMail).setWithLink(false);
try {
userPermission = getDriveService(accessToken).permissions().insert(teamDriveFolderId, userPermission)
.setSupportsTeamDrives(true).execute();
System.out.println(userPermission.toPrettyString());
} catch (IOException e) {
System.out.println(e);
}
System.out.println("[Give Permission] execution time : " + (System.currentTimeMillis() - startTime));
return userPermission;
}
And then I tried to create subfolder using google-drive library several times,
But I failed to create sub-folder continuously.
Create Sub-folder
public static void createSubFolder(String accessToken, String teamDriveFolderId) throws IOException {
long startTime = System.currentTimeMillis();
File fileMetaData = new File();
fileMetaData.setTitle("SubFolder Title ");
fileMetaData.setMimeType("application/vnd.google-apps.folder");
fileMetaData.setTeamDriveId(teamDriveFolderId);
fileMetaData.setParents(Arrays.asList(new ParentReference().setId(teamDriveFolderId)));
fileMetaData.set("supportsTeamDrives", true);
fileMetaData.set("fields", "id");
File file = null;
try {
file = getDriveService(accessToken).files().insert(fileMetaData).execute();
System.out.println(file.getId());
} catch (IOException e) {
e.printStackTrace();
}
System.out.println("[Create Sub folder] execution time : " + (System.currentTimeMillis() - startTime));
}
When I call the 'createSubfolderFunction'
I can get 404 response like this.
com.google.api.client.googleapis.json.GoogleJsonResponseException: 404 Not Found
{
"code" : 404,
"errors" : [ {
"domain" : "global",
"location" : "file",
"locationType" : "other",
"message" : "File not found: 0AHGrQOmlzQZUUk9PVA",
"reason" : "notFound"
} ],
"message" : "File not found: 0AHGrQOmlzQZUUk9PVA"
}
at com.google.api.client.googleapis.json.GoogleJsonResponseException.from(GoogleJsonResponseException.java:146)
'0AHGrQOmlzQZUUk9PVA' is the exact result from createTeamDrive function.
I referred to this question.enter link description here
Please look at my source-code and point out what went wrong.

I found problem myself,
I should add setSupportTeamDrive(true) when I use the insert method.
file = getDriveService(accessToken).files().insert(fileMetaData).setSupportsTeamDrives(true).execute();

I thing issue with the your folder Id check its your parent folder id of google drive is correct or not
$folderId = '0AIuzzEYPQu9CUk9PVA';
Id is present in the google drive folder URL, after you open the parent folder

Related

Google Drive API to identify the changes in files

I have a list of files and folder stored on a google drive folder. My objective is to identify any changes (modify/create/delete) related to any file/folder within a particular google drive folder i.e get the list of these file name and their drive path.
I have not registered any domain as our spring boot application is deployed on K8's pod and I do not want any notification on any domain or any webhook address. I only want the list of files being modified/deleted when I call the below method/api
Below is the code snippet for spring boot application.
#Component
public class DriveServiceProvider {
#Autowired
private DriveConfig dc;
public Drive getDriveService() throws IOException, GeneralSecurityException {
final GoogleCredentials credentials = GoogleCredentials
.fromStream(new ByteArrayInputStream(new JSONObject(dc.getCred()).toString().getBytes()))
.createScoped(Collections.singletonList("https://www.googleapis.com/auth/drive"));
HttpRequestInitializer requestInitializer = new HttpCredentialsAdapter(credentials);
return new Drive.Builder(GoogleNetHttpTransport.newTrustedTransport(), JacksonFactory.getDefaultInstance(), requestInitializer)
.setApplicationName(ApplicationConstants.APPLICATION_NAME).build();
}
}
Controller:
#RestController
#RequestMapping("/admin/watch")
public class TestGoogleWatchController {
#Autowired
private DriveServiceProvider driveServiceProvider;
#PostMapping(value = "/googleWatchNotification")
#ResponseStatus(HttpStatus.OK)
public Channel getNotification() throws IOException, GeneralSecurityException {
try {
StartPageToken pageToken = driveServiceProvider.getDriveService().changes().getStartPageToken().execute();
String savedStartPageToken = pageToken.getStartPageToken();
System.err.println(" savedStartPageToken "+savedStartPageToken );
while (savedStartPageToken != null) {
ChangeList changes = driveServiceProvider.getDriveService().changes().list(savedStartPageToken).execute();
System.err.println("======= changes " + changes.toPrettyString());
System.err.println("============ size ::" + changes.getChanges().size());
System.err.println("============ ChangeList ::" + changes.getChanges());
for (Change changeObj : changes.getChanges()) {
System.err.println(" files "+changeObj.getFileId() + " Kind "+changeObj.getKind() + ", Team Drive ID "+changeObj.getTeamDriveId() + ", Type::"+changeObj.getType()+ ",File ::"+changeObj.getFile()+ ", Is Removed::"+changeObj.getRemoved()+ ",Time ::"+changeObj.getTime());
}
}
}catch(Exception ex) {
}
return null;
}
}
*Below is the output after executing:
savedStartPageToken 165
======= changes {
"changes" : [ ],
"kind" : "drive#changeList",
"newStartPageToken" : "165"
}
============ size ::0
============ ChangeList ::[]*
The savedStartPageToken is printing incrementing numeric value after we change anything in drive, however there the ChangeList is always blank.
I am glad that I am answering my own question. The issue was that I was passing the current token in the changeList api.
Actually, the solution is to find the changes since last token till the current token using a loop.

Google Drive v3 | File Append | com.google.api.client.googleapis.json.GoogleJsonResponseException: 403 Forbidden

Creating a new CustomerData.json file in Google Drive successfully.
Next operation is to update the CustomerData.json file.
On execution of the below code:
File updatedFile = service.files().update(fileId, file, mediaContent).execute();
the application throws the exception with 403: Forbidden.
com.google.api.client.googleapis.json.GoogleJsonResponseException: 403 Forbidden
{
"code" : 403,
"errors" : [ {
"domain" : "global",
"message" : "The resource body includes fields which are not directly writable.",
"reason" : "fieldNotWritable"
} ],
"message" : "The resource body includes fields which are not directly writable."
}
at com.google.api.client.googleapis.json.GoogleJsonResponseException.from(GoogleJsonResponseException.java:146)
at com.google.api.client.googleapis.services.json.AbstractGoogleJsonClientRequest.newExceptionOnError(AbstractGoogleJsonClientRequest.java:113)
at com.google.api.client.googleapis.services.json.AbstractGoogleJsonClientRequest.newExceptionOnError(AbstractGoogleJsonClientRequest.java:40)
at com.google.api.client.googleapis.services.AbstractGoogleClientRequest.executeUnparsed(AbstractGoogleClientRequest.java:432)
at com.google.api.client.googleapis.services.AbstractGoogleClientRequest.executeUnparsed(AbstractGoogleClientRequest.java:352)
at com.google.api.client.googleapis.services.AbstractGoogleClientRequest.execute(AbstractGoogleClientRequest.java:469)
at com.app.gdrive.DriveQuickStart.updateCustomer(DriveQuickStart.java:171)
at com.app.gdrive.DriveQuickStart.main(DriveQuickStart.java:226)
Obviously I went thru the Google API documentation and code samples available on the internet, along with the StackOverflow solutions... still struggling without success.
Create operation - This creates the CustomerData.json file
public static final String createCustomer() throws IOException, GeneralSecurityException, JSONException {
JSONObject jsonObject = new JSONObject();
jsonObject.put("Phone", "3023553505");
jsonObject.put("Name", "Bob Carson");
jsonObject.put("Business", "Spot Clicks");
jsonObject.put("Address", "46 Fairytale Dr, Newark");
jsonObject.put("State", "NJ");
jsonObject.put("Country", "USA");
FileWriter jsonFile = new FileWriter("CustomerData.json");
jsonFile.write(jsonObject.toString());
jsonFile.close();
Drive driveService = getDriveService();
String folderId = "1G9vFaUCsPN6GomJRrK7vML9bSd5Wm63t";
File fileMetadata = new File();
fileMetadata.setName("CustomerData.json");
fileMetadata.setParents(Collections.singletonList(folderId));
java.io.File filePath = new java.io.File("CustomerData.json");
FileContent mediaContent = new FileContent("application/json", filePath);
File file = driveService.files().create(fileMetadata, mediaContent)
.setFields("id, parents").execute();
driveService.permissions().create(file.getId(), new Permission().setRole("writer")
.setType("anyone").setAllowFileDiscovery(false)).execute();
return file.getId();
}
The CustomerData.json file in the drive looks like below:
Update [APPEND] operation - This fails to update the CustomerData.json file
EDIT-1 I need to APPEND additional data into the same json file, I'm not trying to update the existing data in the file.
public static final String updateCustomer(Drive service, String fileId) {
try {
String jsonString = new JSONObject()
.put("Phone", "9840056987")
.put("Name", "Rick Smiley")
.put("Business", "Smiling Bots")
.put("Address", "6 Country Park, Baltimore")
.put("State", "MD")
.put("Country", "USA")
.toString();
File file = service.files().get(fileId).execute();
System.out.println(file.getName());
BufferedWriter writer = new BufferedWriter(new FileWriter(file.getName(), true));
writer.newLine();
writer.write(jsonString);
writer.close();
java.io.File uFile = new java.io.File(file.getName());
FileContent mediaContent = new FileContent("application/json", uFile);
File updatedFile = service.files().update(fileId, file, mediaContent).execute();
return updatedFile.getId();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (JSONException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
return fileId;
}
The SCOPE is defined as
List<String> SCOPES = Collections.singletonList(DriveScopes.DRIVE_FILE);
I tried with DRIVE scope as well... also I deleted the StoredCredential file every time I change the SCOPE.
This code is used for the Desktop App, but later I'm planning use in the mobile app as well.
Quick help is appreciated
I got it resolved - here is the solution
in the updateCustomer() create a new File object like below and use that new object
File updateFile = new File();
updateFile.setName(file.getName());
Use that updateFile object thereafter

Route exchange online public folder hierarchy requests failed with "Expected an item Id but received a folder Id"

Description: We are having the technical difficulties to route the public folder hierarchy if there is a Journal folder, and we are thinking the workaround to use grapy API to do this, but didn't find the information to use Graph API to access the public folder, anyone can share more information would be appreciated.
Environment: Exchange online public folder. And there is one journal folder and one sub folder under the journal folder.
Method: Folder.FindFolders EWS API to route the public folder hierarchy.
Exception: error code: ErrorCannotUseFolderIdForItemId, error: Microsoft.Exchange.WebServices.Data.ServiceResponseException: Expected an item Id but received a folder Id.
Following is the sample code:
public static void GetPublicFolders(Folder parentFolder, int pageSize, int offset, string parentFolderPath)
{
try
{
FindFoldersResults result;
do
{
FolderView folderView = new FolderView(pageSize, offset);
folderView.Traversal = FolderTraversal.Shallow;
result = parentFolder.FindFolders(folderView);
foreach (Folder folder in result)
{
var path = parentFolderPath + #"\" + folder.DisplayName;
System.Console.WriteLine(path);
GetPublicFolders(folder, pageSize, 0, path);
}
offset += pageSize;
}
while (result.MoreAvailable);
}
catch (Exception ex)
{
System.Console.WriteLine(ex);
}
}
Thank you.
Long
A fix is roling out!
This is a problem caused by the Microsoft Exchange WebServices (EWS) of Office365.
As per Microsoft they have found the failure on their Serverside.
Take a look at the comment from Davster (a MS developer) at GitHub (GitHub - EWS MangedAPI issue 204)

How to get Google Drive file ID

I've created a file to Drive root using Google Drive Android API. How can I get this file ID to share it using Google Client Library?
Getting DriveFileResult in ResultCallback<DriveFileResult> callback returns Null:
String fileId = result.getDriveFile().getDriveId().getResourceId();
The callback is to the file being created locally. The DriveId will only have a resourceId when the file is synced to the server. Until then getResourceId will return null.
https://developer.android.com/reference/com/google/android/gms/drive/DriveId.html#getResourceId()
Use CompletionEvents to be notified when syncing with the server has occurred. Then calling getResourceId() should deliver what you are expecting.
this code might help to identify the id for a file present in the google drive.
public static void main(String[] args) throws IOException {
// Build a new authorized API client service.
Drive service = getDriveService();
// Print the names and IDs for up to 10 files.
FileList result = service.files().list()
.setMaxResults(10)
.execute();
List<File> files = result.getItems();
if (files == null || files.size() == 0) {
System.out.println("No files found.");
} else {
System.out.println("Files:");
for (File file : files) {
System.out.printf("%s (%s)\n", file.getTitle(), file.getId());
}
}
}

Google Drive API Upload returns File ID/Title but document does not exist in Drive

I have followed the examples given on the Google Drive SDK site for Authorization via Service Accounts (https://developers.google.com/drive/service-accounts) and to insert a file (https://developers.google.com/drive/v2/reference/files/insert). I have managed to get it working using the Client ID/Client secret with oauth2 but need automation so want to use the private key.
My issue is I am given a file id, Title, Description & MIME type in return e.g. File ID: %s0B6ysbMIcH3AGWHJPRmZUTVZZMnM, Title: My document, Description: A test document, MIME type: text/plain but the document does -not- exist in Drive and no errors are returned.
I have been work on this for 2 days without success and would really appreciate any assistance. I have looked on-line and the examples I have found are similar to the below. I have tried multiple Google accounts (one a company Google Apps & another a normal gmail account with the same result).
The code (with the account info changed) :
public class AutoGoogleDrive {
private static final String SERVICE_ACCOUNT_PKCS12_FILE_PATH = "/home/jsmith/Java/11111111111111111111111111-privatekey.p12";
private static final String SERVICE_ACCOUNT_EMAIL = "1111111111111#developer.gserviceaccount.com";
public static Drive getDriveService() throws GeneralSecurityException,
IOException, URISyntaxException {
HttpTransport httpTransport = new NetHttpTransport();
JacksonFactory jsonFactory = new JacksonFactory();
GoogleCredential credential = new GoogleCredential.Builder()
.setTransport(httpTransport)
.setJsonFactory(jsonFactory)
.setServiceAccountId(SERVICE_ACCOUNT_EMAIL)
.setServiceAccountScopes(DriveScopes.DRIVE_FILE)
.setServiceAccountPrivateKeyFromP12File(
new java.io.File(SERVICE_ACCOUNT_PKCS12_FILE_PATH))
.build();
Drive service = new Drive.Builder(httpTransport, jsonFactory, null)
.setHttpRequestInitializer(credential).build();
return service;
}
public static void main(String[] args) throws IOException {
Drive service = null;
try {
service = getDriveService();
} catch (GeneralSecurityException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (URISyntaxException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
//Insert a text file
File body = new File();
body.setTitle("My document");
body.setDescription("A test document");
body.setMimeType("text/plain");
// File's content.
java.io.File fileContent = new java.io.File("/home/jsmith/document.txt");
FileContent mediaContent = new FileContent("text/plain", fileContent);
try {
File file = service.files().insert(body, mediaContent).execute();
// Uncomment the following line to print the File ID.
System.out.println("File ID: %s" + file.getId());
System.out.println("Title: " + file.getTitle());
System.out.println("Description: " + file.getDescription());
System.out.println("MIME type: " + file.getMimeType());
} catch (IOException e) {
System.out.println("An error occured: " + e);
}
}
}
Thanks,
Joe Smith
When using service accounts, the inserted file will be added to the application's Drive account for which there's no Drive UI. Those files are only available through the API.