google-api-javascript-client : How to get contents of file using Drive API? - google-api

First off, if there is a question/answer that solves my problem already then I sincerely apologize for creating a new one. However, I have been searching for 3 days now, and have not found an answer...
My problem is, I cannot for the life of me figure out how to pull the contents of a file(any file). From reading the docs I've discovered that my returned file resource object is supposed to have a property named "downloadUrl", and from this I should be able to access the file contents.
None of the file resource objects that are returned to me(via gapi.client.request) have this field/property. Below is the function I am using to get a file.
Can someone please help point me in the right direction? I have to have this demo done by Monday and I've been stuck on this for 2 days....
Here is the code for my get function :
Client.getFileContent = function getFileContent() {
gapi.client.load('drive', 'v2', function() {
var request = gapi.client.request({
path : '/drive/v2/files/1QmaofXyVqnw6ODXHE5KWlUTcWbA9KkLyb-lBdh_FLUs',
method : 'GET',
params : {
projection: "FULL"
}
});
request.execute(function(response) {
console.log(response);
});
});
};
The file resource object that is returned to me does not have the downloadUrl property.
As requested, here is the response object I get back for a text file. Note, I replaced some of the ids with "fileid" for posting here.
"kind": "drive#file",
"id": "fileID",
"etag": "\"-tJAWr_lbRQU2o8gZ0X7BCBIlVk/MTM0MjYyODQ1MTQ2Nw\"",
"selfLink": "https://www.googleapis.com/drive/v2/files/fileID",
"alternateLink": "https://docs.google.com/document/d/fileID/edit",
"embedLink": "https://docs.google.com/document/d/fileID/preview",
"thumbnailLink": "https://docs.google.com/feeds/vt?gd=true&id=fileID&v=1&s=AMedNnoAAAAAUAfLhbYIDsNIn40k7DfRYBsrquijmCii&sz=s220",
"permissionsLink": "https://www.googleapis.com/drive/v2/files/fileID/permissions",
"title": "Copied filed.txt",
"mimeType": "application/vnd.google-apps.document",
"labels": {
"starred": false,
"hidden": false,
"trashed": false,
"restricted": false,
"viewed": true
},
"createdDate": "2012-07-18T16:20:51.132Z",
"modifiedDate": "2012-07-18T16:20:51.467Z",
"modifiedByMeDate": "2012-07-18T16:20:51.467Z",
"lastViewedByMeDate": "2012-07-18T16:20:51.467Z",
"parents": [
{
"kind": "drive#parentReference",
"id": "0AAAYYkwdgVqHUk9PVA",
"selfLink": "https://www.googleapis.com/drive/v2/files/fileID/parents/0AAAYYkwdgVqHUk9PVA",
"parentLink": "https://www.googleapis.com/drive/v2/files/0AAAYYkwdgVqHUk9PVA",
"isRoot": true
}
],
"exportLinks": {
"application/vnd.oasis.opendocument.text": "https://docs.google.com/feeds/download/documents/export/Export?id=fileID&exportFormat=odt",
"application/msword": "https://docs.google.com/feeds/download/documents/export/Export?id=fileID&exportFormat=doc",
"text/html": "https://docs.google.com/feeds/download/documents/export/Export?id=fileID&exportFormat=html",
"application/rtf": "https://docs.google.com/feeds/download/documents/export/Export?id=fileID&exportFormat=rtf",
"text/plain": "https://docs.google.com/feeds/download/documents/export/Export?id=fileID&exportFormat=txt",
"application/pdf": "https://docs.google.com/feeds/download/documents/export/Export?id=fileID&exportFormat=pdf"
},
"userPermission": {
"kind": "drive#permission",
"etag": "\"-tJAWr_lbRQU2o8gZ0X7BCBIlVk/9STkNeCmz61YXorH3hoJimnEgfM\"",
"id": "current",
"role": "owner",
"type": "user"
},
"quotaBytesUsed": "0",
"ownerNames": [
"Joshua.morine"
],
"lastModifyingUserName": "Joshua.morine",
"editable": true,
"writersCanShare": true
}

For native Google documents (Google Spreadsheet, Presentation etc...) we don;t provide a downloadUrl as these can't really be downloaded as files in their native format. Instead you'll have to use one of the URLs in the list of exportLinks which provides URLs to download the Google Documents in a few different export formats.
In your case, a Google Documents the following can be used:
"exportLinks": {
"application/vnd.oasis.opendocument.text": "https://docs.google.com/feeds/download/documents/export/Export?id=fileID&exportFormat=odt",
"application/msword": "https://docs.google.com/feeds/download/documents/export/Export?id=fileID&exportFormat=doc",
"text/html": "https://docs.google.com/feeds/download/documents/export/Export?id=fileID&exportFormat=html",
"application/rtf": "https://docs.google.com/feeds/download/documents/export/Export?id=fileID&exportFormat=rtf",
"text/plain": "https://docs.google.com/feeds/download/documents/export/Export?id=fileID&exportFormat=txt",
"application/pdf": "https://docs.google.com/feeds/download/documents/export/Export?id=fileID&exportFormat=pdf"
}

The meta-data function you are looking for is actually:
request = gapi.client.drive.files.get({
'fileId': fileId
});
This one produces a result with the downloadUrl that you're referring to. Then it's easy to grab the file using any HTTP request.

Related

Cypress: want to partially mock XHR response

I am using Cypress and I want to stub the XHR response partially. I want to catch the original JSON, and edit it partially.
for instance:
cy.route('GET', `**/subjects`, 'fixture:mySubjects.json');
this way i am stubbing the whole response, but I want to see:
original XHR response (of course with many other properties) :
{
'id': 12345,
"subjects": [
{
"key": "mat",
"name": "maths",
"hasAccess": true,
},
{
"key": "eng",
"name": "english",
"hasAccess": false,
}
],
}
what I want to stub is only name, and want to get:
{
'id': 12345,
"subjects": [
{
"key": "mat",
"name": "maths",
"hasAccess": true,
}
],
}
In short, what I wanted to do is to remove the second subject 'eng' from the response. any idea is much appreciated.
Take a look at cy.intercept().
I don't quite understand what parts of the real response you want to return or stub, but this is the mechanism to do so.
cy.intercept('/integrations', (req) => {
// req.reply() with a callback will send the request to the destination server
req.reply((res) => {
// 'res' represents the real destination response
// you can manipulate 'res' before it's sent to the browser
})
})
If you are using a Cypress version < 6 you can try using cy.route2() with the same syntax.

Get the list of action items from Google Drive API

Hi, everyone.
I have been trying to use Google Drive API for getting a list with the action items assigned in all files (docs or spreadsheets) in my company's domain using Spring Boot and the google-api-services-drive, but I have faced some issues:
Looks like there is nothing about action items on the API.
Comments are the closest I could get, but they don't include action item information. They only have the emails of people who were mentioned.
Documentation looks broad and not precise. For instance, here they say files resources include an indexableText property, but it is not present on the response.
As explained in Term for followup, looking for actionitems you can apply a query for getting the files with action items. Why is the fullText field not available in the response, or some other equivalent attribute to see the actual content and use it as a workaround to get the action items?
I just need to know who was assigned to the action item from the comment.
Any ideas?
Retrieve the action items with Comments: list specifying fields as comments/replies/action
I agree with you that it is not straightfoward, but there is a way to retrieve the full comment content including action items.
Use Files:list specifying q as fullText contains 'followup:actionitems', just as in the post you mentioned
For each of the retrieve items, use the fileId for the method Comments: list
For better understadning specify first the fields for Comments:list as * - this will return you the complete reponse looking as following:
{
"kind": "drive#commentList",
"comments": [
{
"kind": "drive#comment",
"id": "AAAAGlyxwAg",
"createdTime": "2020-06-08T09:04:34.907Z",
"modifiedTime": "2020-06-08T09:05:07.279Z",
"author": {
"kind": "drive#user",
"displayName": "XXX",
"photoLink": "//ssl.gstatic.com/s2/profiles/images/silhouette96.png",
"me": true
},
"htmlContent": "+\u003ca href=\"mailto:YYY#YYY.com\" data-rawHref=\"mailto:YYY#YYY.com\" target=\"_blank\"\u003eYYY#YYY.com\u003c/a\u003e Could you please check the spelling?",
"content": "+YYY#YYY.com Could you please check the spelling?",
"deleted": false,
"resolved": true,
"quotedFileContent": {
"mimeType": "text/html",
"value": "Hello"
},
"anchor": "kix.94ksxclyqix",
"replies": [
{
"kind": "drive#reply",
"id": "AAAAGlyxwAo",
"createdTime": "2020-06-08T09:05:02.999Z",
"modifiedTime": "2020-06-08T09:05:02.999Z",
"author": {
"kind": "drive#user",
"displayName": "YYY",
"photoLink": "//ssl.gstatic.com/s2/profiles/images/silhouette96.png",
"me": false
},
"htmlContent": "Will do!",
"content": "Will do!",
"deleted": false
},
{
"kind": "drive#reply",
"id": "AAAAGlyxwAs",
"createdTime": "2020-06-08T09:05:07.279Z",
"modifiedTime": "2020-06-08T09:05:07.279Z",
"author": {
"kind": "drive#user",
"displayName": "YYY",
"photoLink": "//ssl.gstatic.com/s2/profiles/images/silhouette96.png",
"me": false
},
"deleted": false,
"action": "resolve"
}
]
}
]
}
This response contains the following information:
The quoted file content (the text to which the comment refers)
The content of the initial comment and the replies
The user to whom the comment was assigned
The reply of the user including his user name
And finally, the action taked by the user
Now, if you are not interested in all fields but only in the action, you can see that action is a resources nested in comments/replies
To query for action, replace the * in fields with comments/replies/action
as for your question about indexableText, the documentation specifies that it is a property of contentHints and
contentHints
Additional information about the content of the file.
These fields are never populated in responses.
A way to make indexableText "useful" is e.g. apply it in queries like
Files:list with q : fullText contains 'indexableText'
The good new are that if you not happy with the way how actions are retrieved now and can think of a better method to implement it, you can file a Feature request on Google's Public Issue Tracker. If enough users show interest in the feature, Google might implement it in the future.

Google Drive Public File Permissions

Let's say I have a public folder which is not discoverable. If I expose the File ID of one of the files for download, is it possible for an untrusted user to obtain a link to the folder which contains that file, or a link to other files within that folder? I've done a search on the Google APIs but haven't found anything relevant.
Edit:
Seems like some of you guys still don't get the question. So let me illustrate with a diagram. Let's say I have a public folder in Google Drive:
Folder A |
|-- File X
|-- File Y
|-- File Z
So the question is, if someone else has the File ID of File X, which I'm fine with, then can he get the File ID of Folder A? Or the File IDs of Files Y and Z? That's where I'm concerned.
If you create a file on Google drive it is just that public.
If you share the file with me, then I have access to it.
If i install an application that has access to my google drive account the owner of the app has access to it (Really they ahve access to all my files)
If i give a copy of the link to my friend they can access it.
I can technically also see what directory the file is in. I can then make a request to see what other files may be within this directory. If the directory is public then I have access to that information.
Only the file you set to public will be accessible.
Files within the same directory as a public file will not be public.
The parent directory will not be public just because it contains a public file.
The point with public drive files is anyone can access them without permissions. The only security you have is that Tom on the street cant just do a search and find your file, or can they will it popup in google search someday?
Update file id:
If you expose the file id then i can take the file id and download the file using the API just like you can using a public api key or using the Google APIs explorer. The file is public anyone can download it that has the id. It was also possible in the past to take the file id and use that to create a URL for download directly though the Google Drive website.
https://docs.google.com/spreadsheets/d/{FileID}/edit#gid=0
https://drive.google.com/drive/folders/{FileID}
This does not always work anymore mostly with files that are of type Google doc.
I can also use the file id to see what directory the file is in and request a list of files within that directory.
Example Testing with a given file id
https://www.googleapis.com/drive/v2/files/1AzP6ISIrC8CvK3rTZfNBJ8qZL6LwcaSI?key={my api key}
or just use the try me on this page
Files.Get
Response
{
"kind": "drive#file",
"id": "1AzP6ISIrC8CvK3rTZfNBJ8qZL6LwcaSI",
"etag": "\"G9mQazc6pdRCuGfUPB_oyY074Ug/MTUxNTY5MzM4NjYxNA\"",
"selfLink": "https://www.googleapis.com/drive/v2/files/1AzP6ISIrC8CvK3rTZfNBJ8qZL6LwcaSI",
"webContentLink": "https://drive.google.com/uc?id=1AzP6ISIrC8CvK3rTZfNBJ8qZL6LwcaSI&export=download",
"alternateLink": "https://drive.google.com/file/d/1AzP6ISIrC8CvK3rTZfNBJ8qZL6LwcaSI/view?usp=drivesdk",
"embedLink": "https://drive.google.com/file/d/1AzP6ISIrC8CvK3rTZfNBJ8qZL6LwcaSI/preview?usp=drivesdk",
"iconLink": "https://drive-thirdparty.googleusercontent.com/16/type/image/png",
"thumbnailLink": "https://lh3.googleusercontent.com/_vX1BrFIsR-lVnFR1-VS9tp2toDLNfE6Cf1m3RGEIG7--VQfp53OiNbrnLC_rOGmqUbfn6QHQ7c=s220",
"title": "splash.png",
"mimeType": "image/png",
"labels": {
"starred": false,
"hidden": false,
"trashed": false,
"restricted": false,
"viewed": false
},
"createdDate": "2018-01-11T09:31:51.426Z",
"modifiedDate": "2018-01-11T17:56:26.614Z",
"markedViewedByMeDate": "1970-01-01T00:00:00.000Z",
"version": "8",
"parents": [],
"downloadUrl": "https://doc-0g-6o-docs.googleusercontent.com/docs/securesc/1mngaurn1r7pdnvlih02e6t9l8me2de5/3q2i7ak140vftlc9c96evgvnsmri4m4v/1517565600000/18429462472537742596/06030588225573437243/1AzP6ISIrC8CvK3rTZfNBJ8qZL6LwcaSI?e=download&gd=true",
"userPermission": {
"kind": "drive#permission",
"etag": "\"G9mQazc6pdRCuGfUPB_oyY074Ug/WUHObW5vTApa-BsGvLisiOGqWbA\"",
"id": "me",
"selfLink": "https://www.googleapis.com/drive/v2/files/1AzP6ISIrC8CvK3rTZfNBJ8qZL6LwcaSI/permissions/me",
"role": "reader",
"type": "user"
},
"originalFilename": "splash.png",
"fileExtension": "png",
"md5Checksum": "108e62ba72a0b33cb4bc7628e48d2e2c",
"fileSize": "22375",
"quotaBytesUsed": "0",
"ownerNames": [
"WU JUANG CHEN"
],
"owners": [
{
"kind": "drive#user",
"displayName": "WU JUANG CHEN",
"isAuthenticatedUser": false,
"permissionId": "18429462472537742596",
"emailAddress": "XXXX#connect.hku.hk"
}
],
"lastModifyingUserName": "WU JUANG CHEN",
"lastModifyingUser": {
"kind": "drive#user",
"displayName": "WU JUANG CHEN",
"isAuthenticatedUser": false,
"permissionId": "18429462472537742596",
"emailAddress": "xxxxx#connect.hku.hk"
},
"capabilities": {
"canCopy": true,
"canEdit": false
},
"editable": false,
"copyable": true,
"writersCanShare": true,
"shared": true,
"explicitlyTrashed": false,
"appDataContents": false,
"headRevisionId": "0B-l1jDyJ1EfRZERkZnJmcUZxRHlkUzk0bEx6bmhMUzd3WXdrPQ",
"imageMediaMetadata": {
"width": 375,
"height": 812,
"rotation": 0
},
"spaces": [
"drive"
]
}
Analytics
I have your email address "emailAddress": "XXXX#connect.hku.hk" and name
A view link of the file https://drive.google.com/file/d/1AzP6ISIrC8CvK3rTZfNBJ8qZL6LwcaSI/view?usp=drivesdk as well as a download link for it.
Note: "parents": [], should contain the ID of the parent directory for this file. I am going to assume that its either private or in your root directory. If you say that the directory for this file is public i think its an awesome feature of google not to display this.
Which would mean that the answer is if you have the file id you dont necessarily get access to the folder id.

Google Drive API upload file with custom property, properties missing from response

I am trying to save a google drive file with custom properties, but its not working and due to the very poor documentation of the Google API, i am struggeling with this. Here is my code so far:
$g = new FileCtrl();
$fileMeta = new Google_Service_Drive_DriveFile();
$fileMeta->name = $file['name'];
$fileMeta->parents = [$g->googleDriveFolderId];
$fileMeta->appProperties = (object)['lead_id'=>$file['lid'], 'sales_package_id'=>$file['pid'], 'user_id'=>$user->uid];
//$fileMeta->size = $file['size'];
$fileData = array(
'data' => $fileContent,
'mimeType' => $file['media_type'],
'uploadType' => $file['multipart'],
);
//create file in google drive
$res = $g->client->files->create($fileMeta, $fileData);
It is not returning an error and the event is saved, but without the custom properties!?
You are probably looking for the properties in the returned file resource.
The reason they aren't there is that Drive only returns a small number of the file properties (name, mime type, id). If you want to see the full file resource you need to include fields=* in the request. So a correct request would look something like
POST https://content.googleapis.com/drive/v3/files?fields=*
I don't know the PHP library, so you'll need to figure that bit out. It will be something like
'fields' => '*',
I just tested this.
Request:
{
"name": "Linda Test",
"mimeType": "application/vnd.google-apps.document",
"appProperties": {
"TestingId": "1"
}
}
Response:
{
"kind": "drive#file",
"id": "1mhP2EW4Kbl81F5AuJ4zJ2IPoeI56i_Vd5K-dfGJRj6Y",
"name": "Linda Test",
"mimeType": "application/vnd.google-apps.document"
}
Do a file.get to check the file metadata.
{
"kind": "drive#file",
"id": "1mhP2EW4Kbl81F5AuJ4zJ2IPoeI56i_Vd5K-dfGJRj6Y",
"name": "Linda Test",
"mimeType": "application/vnd.google-apps.document",
"starred": false,
"trashed": false,
"explicitlyTrashed": false,
"parents": [
"0AJpJkOVaKccEUk9PVA"
],
"appProperties": {
"TestingId": "1"
},
...
}
I suggest you check your uploaded file using the File.get method after its returned to be sure that it was added. To my knowledge there is now way to see these added fields via the Google drive website interface. If after ruining a file.get you still find that it wasn't uploaded i suggest you log this as a bug with the Google APIs PHP client library team. This works with raw rest requests it could be an issue with the library.

Intel XDK : Parse.com integration "Unauthorized"

I am very new to Intel XDK and i try to make a very simple app like this in that video tutorial: Using Services Datafeed in App Designer.
But instead of the specific service from Rotten Tomatoes i want to integrate a database i have in Parse.com. For that i followed this video tutorial: "Integrating a New Service"
"[https]://software.intel.com/en-us/html5/videos/integrating-a-new-service",
and at the end the response was: "Unauthorized".
Then i found only this answer which comes from Intel's HTML5 Development Forums. I did not get anything either with this. The response was again: "Unauthorized".
And now i am confused and disappointed because:
I can't find other resources to help my self
I don't want to do it someone else instead of me, but
Without a full example, how is supposed to make it to learn?
My code now is similar with this in video: "Integrating a New Service"
In apiconfig.json
{
"MyService": {
"name": "The external service",
"description": "A great API with an external service",
"dashboardUrl": "https://parse.com",
"auth": "key",
"signature": "apiSecret"
}
}
In MyService.js
(function (credentials) {
var exports = {};
exports.ServiceObject = function(params) {
var url = 'https://api.parse.com/1/classes/ServiceObject';
params['apiKey'] = credentials.apiKey;
url = url + '?' + $.param(params);
return $.ajax({url: url, type: 'GET'});
};
return exports;
})
And in MyService.json
{
"endpoints": [
{
"name": "classes",
"dashboardUrl": "https://parse.com/docs/rest",
"methods": [
{
"MethodName": "ServiceObject",
"Synopsis": "Show the entries",
"parameters": [
{
"Name": "objectId",
"Required": "N",
"Default": "",
"Type": "string",
"Description": "The object ID"
},
{
"Name": "text",
"Required": "N",
"Default": "",
"Type": "string",
"Description": "The text"
}
]
}
]
}
]
}
Can someone help me more? In whatever way he thinks best.
Thank you all
Edit:
After the following answer, my problem solved.
"MyService.js" file after the correction is:
(function (credentials) {
var exports = {};
exports.ServiceObject = function(params) {
var url = 'https://api.parse.com/1/classes/ServiceObject';
return $.ajax({
url : url,
headers : {
'X-Parse-Application-Id' : credentials.apiKey,
'X-Parse-REST-API-Key' : credentials.apiSecret
}
});
};
return exports;
})
# user1736947: Your answer was concise and precise, exactly what i needed.
Certainly in the future I will need a lot of help, but for now I can go on my self-education thanks to you.
Thank you very much.
The way the authentication keys are accepted is different for different services. The example in the video.. rottentomatoes.. it accepted keys as a url parameter, so we append the key to the url and send it. However, seems like parse wants the keys in the headers (according to this)
So the equivalent ajax call will be something like :
exports.ServiceObject = function(params) {
var url = 'https://api.parse.com/1/classes/ServiceObject';
return $.ajax({
url : url,
headers : {
'X-Parse-Application-Id' : credentials.apiKey,
'X-Parse-REST-API-Key' : credentials.apiSecret
}
});
This might not fix everything but it will move you a step beyond the authorization issue. Let me know if you are able to retreive the class this way.
To get a particular row entry, append the url with params.objectID.
Also, the XDK services tab has a parse-similar service ... kinvey. It also allows you to create a database online and retreive it.

Resources