How to create a Google Drive folder using node.js with googleapis official module - node.js

I'm trying this way:
var oauth2Client = new OAuth2(GDRIVE_CLIENT_ID, GDRIVE_CLIENT_SECRET, GDRIVE_REDIRECT_URI);
oauth2Client.setCredentials({
access_token: some_valid_access_token
});
drive.files.insert({
auth: oauth2Client,
resource: {
mimeType: 'application/vnd.google-apps.folder',
title: 'my new folder'
}
},function(err,response){
if(err){
console.log('error at gdrive creat folder: ' + util.inspect(err));
}else{
console.log('create response: ' + util.inspect(response));
}
});
And getting an error:
You cannot upload content to files of type application/vnd.google-apps.folder
What's the correct way of doing this?

The error message means that you (or the library on your behalf) is trying to upload content. This makes sense for regular files, but not for folders which have no content.
So either:-
You're not using the library correctly and there is a content-less insert you should be using
It's a bug in the library
I would suggest raise an issue on the GitHub project https://github.com/google/google-api-nodejs-client and update this question with whatever response you get.
If it's holding you up, just replace the library call with a really simple POST to the Drive endpoint with your "resource" as the POST body. You might find it's so easy that you throw the library away and do it all yourself.

Related

nodejs - Getting 401 error trying to download docs revisions with Google Drive API export links

I need to download all the revisions of a google doc with the Drive API using nodejs but I don't understand how to authorize the request for the export links. Once I get the export link for each revision I call:
var options = {
url: 'https://docs.google.com/feeds/download/documents/export/Export?id=1DRl6rbcVuuLVyb_WlhBLiYiCByWcS2bKGlLIsn7E8_8&revision=1&exportFormat=txt', //example link
method: 'GET',
headers: {
Authorization: `Bearer ${jwToken}`,
},
}
request(options).pipe(fs.createWriteStream(mydownloadfilename));
where the "jwToken" is the token I use to get the revisions list so I guess it should be still valid. However, with this I get the 401-Unauthorized page. What am I doing wrong?
Thanks
According to the Drive API v3 documentation:
Revisions for Google Docs, Sheets, and Slides can't be downloaded.
So essentially, if the actual revision you want to retrieve is the file itself, then the method above is the correct one.
As for the authorization part, you will need to perform the Node.js Quickstart from here and follow the steps explained there.
Since you want to export the file, you will just need to modify the code and add this part:
function downloadDoc() {
var fileId = 'ID_OF_THE_DOC';
var dest = fs.createWriteStream('DESTINATION_OF_THE_OUTPUT_STREAM');
drive.files.export({
fileId: fileId,
mimeType: 'application/vnd.google-apps.document'
})
.on('end', function () {
console.log('Done');
})
.on('error', function (err) {
console.log('Error during download', err);
})
.pipe(dest);
}
Reference
Drive API v3 - Manage Revisions;
Drive API v3 - Files:export;
Drive API v3 - Quickstart;
Drive API v3 - Download a document.
I am facing this same problem. The solution is to use
OAUTH2 authorization for a user that has Edit or Owner permissions for a file
Get an access token that expires quickly
call the V2 URI (V3 does not work) for the file/rev to get "export links" 3) Call the correct export link for your format type
then you will get a randomized temporary redirect link from Google that you can then call to get the binary stream.
This is a great starting point for C# .NET -- windows oauth console app, if you want working code to do steps 1 and 2. I posted a working v2 code function here that you can put into the console app example.

Generate .ics url like Basecamp in Nodejs

I am working on nodeJs(backend) and (Angular)
I want to generate a .ics file URL for google calendar and for Apple and Microsoft as a downloadable file.
I know there is a node module ics and I am using that, but that only creates a .ics file I want this to be unique for each user and also want this to delete automatically.
Also, it should automatically sync with the events added.
any suggestion for this?
I have been unable to find a way that would continually update someone's schedule since this would require continuous access to someone's calendar. While building a scheduling site I got around your storage and unique file problem by using a brute force solution.
First, as a client access the download endpoint an unique ics file is generated and stored as schedule_date_client-name.ics. This unique file is then sent to the user using res.download and promptly deleted using fs.unlink(path_to_file).
Here is an example of this in action :
try {
res.download(path, function(error){
if (error) {
console.log("Error : ", error)
}
fs.unlink(path, (error) => {
// log any error
if (error) {
console.log(error);
}
})
});
} catch (e) {
next(e);
}
The best way I found around this is to generate the .ics file as the user accesses a /download url endpoint. Send the file in a downloadable format using res.download in your controller file. Here is more information on the packages I used for this solution :
Node .ics : https://www.npmjs.com/package/ical-generator
Node file : https://nodejs.dev/learn/the-nodejs-fs-module
Require the modules :
const ical = require('ical-generator');
const fs = require("fs");

Upload file to SharePoint via REST API with gulp spsave

I am trying to upload a file (PDF) from a local directory to a document library on SharePoint. I have a gulp build system in place that watches the folder for changes and runs a task that pipes the PDF stream through gulp-spsave
gulp-spsave is nice because it abstracts away what appears to be a pretty complex SharePoint REST interface, where I can supply my credentials, url, and upload folder and it does the rest.
However, I keep getting a 404. I'm new to SharePoint and don't really understand the URL structure, so I'm guessing I'm not supplying the correct info to the plugin.
This is the URL to the document library (which is named DST):
https://{subdomain}.{customdomain}.com/depts/indirectsales/DST/Forms/AllItems.aspx
And this is my gulp task:
gulp.task('upload', function() {
var catalog = paths.output + 'catalog.pdf';
return gulp.src(catalog)
.pipe(spsave({
username: '{user}',
password: '{pass}',
siteUrl: 'https://{subdomain}.{customdomain}.com/depts/indirectsales/',
folder: 'DST'
}));
});
I have tried other combinations of siteUrl and folder to no avail, such as:
siteUrl: 'https://{subdomain}.{customdomain}.com',
folder: 'depts/indirectsales/DST'
Does anyone know what the correct strings would be for siteUrl and folder given the document library URL?
EDIT: It looks like I'm trying to connect to an on-premises Sharepoint 2010 installation, and spsave works only for 2013/2016 and SPO. Does anyone know how to upload a file to a document library in SP 2010 using REST?
It turns out the only reason I was having problems with a standard REST request was because I wasn't authenticating to SharePoint with NTLM. I was able to do so with the http-ntlm module in node:
httpntlm.post({
url: 'http://domain.com/site/_vti_bin/copy.asmx',
headers: {
'SOAPAction': 'http://schemas.microsoft.com/sharepoint/soap/CopyIntoItems',
'Content-Type': 'text/xml; charset="utf-8"'
},
username: 'user',
password: 'pass',
body: soapEnv,
}, function(err, response) {
//callback
}

Google Spreadsheet Creation - Node.js

I am trying to create new google spreadsheet using the google spreadsheet api using node.js
I have managed to get the Google OAuth 2.0 working, where I am getting the access tokens for the clients.
Now on searching the Google API docs there are example using the gData client library but nothing giving me pointers to node.js
Here are my findings for creating a new google spreadhseet
Upload a spreadsheet manually OR
Use a resumable upload link
There is not much information on the resumable upload link.
I can see the HTTP Post Request and Response but I do not understand how to construct the post request in node.js
EDIT--
I am reading Google Apps Platform
Here is how to do it with the create method of the Google Sheets API (currently v4).
This code examples does not use any 3rd party libraries, it uses googleapis: Google API's official Node.js client
const google = require('googleapis');
const sheets = google.sheets('v4');
// authenticate, and store that authentication, in this example
// it is stored in a variable called `auth`. I am using JWT
// authentication, but you can use the any form of authentication
const auth = new google.auth.JWT(
key.client_email,
null,
key.private_key,
['https://www.googleapis.com/auth/spreadsheets'], // make sure that your auth scope includes `spreadsheets`, `drive` or `drive.file`
null
);
sheets.spreadsheets.create({
auth: auth,
resource: {
properties: {
title: 'Title of your new spreadsheet'
}
}
}, (err, response) => {
if (err) {
console.log(`The API returned an error: ${err}`);
return;
}
console.log('Created a new spreadsheet:')
console.log(response);
});
If all you want to know is how to construct post request, then check this example
http://nodejs.org/api/http.html#http_http_request_options_callback
Checkout
https://github.com/EastCloud/node-spreadsheets/
EastCloud has written a friendly-ish wrapper around the Google Docs/Drive API
If you are new and want to get and add data to Google spreadsheets, please refer below link to get step-by-step guide.
https://www.twilio.com/blog/2017/03/google-spreadsheets-and-javascriptnode-js.html
I was tested same in recent nodejs project

Upload a photo to facebook album

I have a nodejs (+express + mongodb,gridstore) backend, and want to upload a photo to a facebook album.
I came across 2 methods. the first ( https://developers.facebook.com/blog/post/526/ ) needs to get the full url resource of my picture, which I don't have as it is data that I pull from gridstore,
and the second ( https://developers.facebook.com/docs/reference/api/album/ ) is very poorly documented, via the Graph API, where I can't figure out what my request should look like. (the form-data, what fields should it have, how to convert my data blob\stream from gridstore to it)
Here is what I currently have, and doesn't work:
facebook.uploadPhoto = function (token, albumId, photo, callback) {
var fb = fermata.json('https://graph.facebook.com/' + albumId);
fb.photos({access_token:token}).post({'Content-Type':"multipart/form-data"}, {source:{data:photo}}, callback);
};
Any help would be much appreciated
There is a good chance the file is not properly serialized. Fermata will take a node File buffer via data. Have you tried passing that instead?
fs.readFile("/path/to/photo.jpg", function (err, data) {
fermata.json("https://graph.facebook.com/graph/api").post({"Content-Type":"multipart/form-data"}, {fileField: {data:data, name:"", type:""} }, callback);
});
Adding your access token etc..
I solved this problem by using a simple POST to the facebook graph API using the poster module.
var options = {
uploadUrl: 'https://graph.facebook.com/'+user+'/photos?access_token='+accessToken,
method: 'POST',
fileId: 'source',
fields: {'message':''} // Additional fields according to graph API
};
var fileName = ''; // Local or remote url where to find the image
poster.post(fileName, options, function(err, data) {
if (err) {
//Something went wrong
} else {
// Everything ok
}
});
Honestly, I've got limited experience working with the Facebook graph API and mostly using PHP and Java.
Here is some streams that you might find helpful:
Upload Photo To Album with Facebook's Graph API
Facebook Graph API - upload photo using JavaScript
Basically, I recommend you punt a little in your implementation and code it in the following way:
Create a REST web service function call in Node.js to output a single image from gridstore using an internal UID.
Code your uploadToFacebook function to use an image URL that calls the REST web service function.
Basically, this would allow you to validate the image output by pointing your browser to the REST web service and avoid any blob\stream conversions inside your uploadToFacebook function. I'm assuming you store the image in gridstore vs. mongodb.
hope that helps...

Resources