Upload file to google drive using REST API in Node.js - node.js

I am trying to upload a file to google drive using rest API(insert) in node.js, I have access_token and refresh_token. how can I upload without any sdk.

I was successful in testing this NodeJS upload by modifying the NodeJS basic upload sample a bit and mixing it with the already available NodeJS Quickstart
Here's the upload function:
function uploadFile(auth){
var drive = google.drive('v3');
var fileMetadata = {
'name': 'uploadImageTest.jpeg'
};
var media = {
mimeType: 'image/jpeg',
//PATH OF THE FILE FROM YOUR COMPUTER
body: fs.createReadStream('/usr/local/google/home/rrenacia/Downloads/noogui.jpeg')
};
drive.files.create({
auth: auth,
resource: fileMetadata,
media: media,
fields: 'id'
}, function (err, file) {
if (err) {
// Handle error
console.error(err);
} else {
console.log('File Id: ', file.id);
}
});
}
You can use the NodeJS Quickstart as reference for authorization. Change listFiles function name:
authorize(JSON.parse(content), listFiles);
to the name of your upload function, in this case:
authorize(JSON.parse(content), uploadFile);
A sucessful upload on my Google drive:

Check this out Node.js QuickStart for Google Drive

Related

User puts image to post and other users want to see it [duplicate]

I am building a web application using the MERN stack (MongoDB, Express Server, ReactJS front end and NodeJS back end) and was wondering some good ways to store images from the back end.
In the past, I have used Firebase for authentication and storage directly from the front end. As I am handling my own user authentication model in MongoDB, is it possible to still use firebase storage and if so would it be from the front end or back end. If it was from the front end, how would I secure it without having firebase authentication?
Other options I have read into are storing images into MongoDB using GridFS or storing on the server using Multer.
Once I have a solution in mind, I will be able to read the docs and figure out how to get it done.
Any advice is appreciated.
An option is to upload the image to Cloudinary in the client-side and save the returned URL to MongoDB with your own API. Cloudinary does more than hosting your images but also handles image manipulation and optimization and more.
Basically what you will have to do is:
Sign up for a Cloudinary account
Go to Settings -> Upload
Add an "upload preset" with 'Unsigned mode' to enable unsigned uploading to Cloudinary
Then your upload function can be something like this:
async function uploadImage(file) { // file from <input type="file">
const data = new FormData();
data.append("file", file);
data.append("upload_preset", NAME_OF_UPLOAD_PRESET);
const res = await fetch(
`https://api.cloudinary.com/v1_1/${YOUR_ID}/image/upload`,
{
method: "POST",
body: data,
}
);
const img = await res.json();
// Post `img.secure_url` to your server and save to MongoDB
}
I think using multer is the very convenient way.
You can upload the images into a folder using multer and store the reference URL in MongoDB. It is also important if you are willing to host your MERN application. You don't need any third party help like firebase or Cloudinary uploads and authentications (you have done this already).
So you can host your own app using your own functionalities. No external cost (just for the domain :D)
This may help you to get a brief idea.
const InstrumentImageStore = multer.diskStorage({
destination: function (req, file, callback) {
const userId = req.userId;
const dir = `instrumentImgs/${userId}`;
fs.exists(dir, (exist) => {
if (!exist) {
return fs.mkdir(dir, (error) => callback(error, dir));
}
return callback(null, dir);
});
},
filename: function (req, file, callback) {
callback(null, Date.now() + "-" + file.originalname);
},
});
router.post(
"/add/instrument",
[isauth, multer({ storage: InstrumentImageStore }).array("imageArr", 5)],
//isauth is another middleware that restricts requests using JWT
instrumentController.addInstrument
);
I ended up implementing Firebase Storage from the Firebase Admin SDK and using Multer to store images in memory until I load them to Firebase.
https://firebase.google.com/docs/storage/admin/start
const uploader = multer({
storage: multer.memoryStorage(),
limits: {
fileSize: 5 * 1024 * 1024,
},
});
// #route POST api/users/upload/avatar
// #desc Upload a new avatar and save to storage
// #access Private
router.post('/upload/avatar', [auth, uploader.single('image')], async (req, res, next) => {
if (!req.file) {
res.status(400).json({ msg: 'No file submitted.' });
return;
}
try {
const blob = firebase.bucket.file(req.file.originalname);
const blobStream = blob.createWriteStream({
gzip: true,
resumable: false,
metadata: {
contentType: req.file.mimetype,
},
});
blobStream.on('error', (err) => next(err));
blobStream.on('finish', () => {
publicUrl = `https://firebasestorage.googleapis.com/v0/b/${
firebase.bucket.name
}/o/${encodeURI(blob.name)}?alt=media`;
res.status(200).json({
photoURL: publicUrl,
});
User.findById(req.user.id).then((user) => {
user.photoURL = publicUrl;
user.save();
});
});
blobStream.end(req.file.buffer);
} catch (error) {
console.error(error.message);
res.status(500).send({ msg: 'A Server error occurred' });
}
});
Thought this might be helpful if someone stumbles upon this post in the future.
You can wire up any external authentication system to Firebase Authentication by [implementing a custom provider](https://firebase.google.com/docs/auth/web/custom-auth for the latter.
This requires that you run code in a trusted environment, such as a server you control or Cloud Functions, where you take the authentication results of the user and convert them into a Firebase Authentication token.
The client-side then signs into Firebase with that token, and from that moment on Storage (and other services) knows about the user just as before.

google drive api upload success return id. but file not exist in drive?

upload success with return id. and tried to drive.files.list that too. it exists. but file not exist in drive? what is this? I try to upload in specific folder by id. wheres file upload location?
const { google } = require('googleapis');
const fs = require('fs');
const credentials = require('./credentials.json');
const scopes = [
'https://www.googleapis.com/auth/drive'
];
const auth = new google.auth.JWT(
credentials.client_email, null,
credentials.private_key, scopes
);
const drive = google.drive({ version: 'v3', auth });
(async () => {
const fileMetadata = {
name: 'naruto.jpg'
};
const media = {
mimeType: 'image/jpeg',
body: fs.createReadStream('naruto.jpg')
};
const res = await drive.files.create({
q: `'1PhND1fjEDnL63BbrLmw2V4M4B6jIfP8Q' in parents`,
resource: fileMetadata,
media: media,
fields: 'id'
});
console.log(res.data);
})();
You appear to be using a service account. A service account has its own google drive account and in your case you appear to have uploaded the file to the Service accounts google drive account.
If you want to upload the file to your own personal google drive account you should share a directory with the service account on your personal drive account and then when you create the file metadata make sure to set the parent directory where you would like the file uploaded to .
let fileMetadata = {
'name': 'icon.png',
'parents': [ '10krlloIS2i_2u_ewkdv3_1NqcpmWSL1w' ]
};
Code ripped from Upload Image to Google drive with Node Js also
Google drive API upload file with Nodejs + service account

get public shareble link after uploading file to google drive using nodejs

i want to upload files to google drive using nodeJS as backend. I have used google drive API v3. I get the file id and type in response after uploading a file.
drive.files.create({
resource: {
name: 'Test',
mimeType: 'image/jpeg'
},
media: {
mimeType: 'image/jpeg',
body: fileData
}
}, function(err, result){
if(err)
res.send(err);
else
res.send(result);
});
but what i want is when i upload a file i want it as publicly accessible. i want the shareable link of that file in response. Is there any way to do so ? i have implemented the way given here : https://developers.google.com/drive/v3/web/manage-sharing which works fine with s.showSettingsDialog(). But i want the shareable link at the time i upload the file.
You could simply save this url < https://drive.google.com/open?id=FILE_ID > in your database and replace the FILE_ID with the actual file id stored in your google drive which in your case would be result.id

Node: Google Drive API for listing all files using query

May I know how can I list all the files using query in the Google Drive using the GoogleAPIS library
https://github.com/google/google-api-nodejs-client/
I have no idea, how to use this library!
I dont know where should I place my query, I have tried the code below, but I am not getting any response..
Test 1:
drive.files.list("mimeType='image/jpg'", function(data){
//I am getting all the data, the query is not working..
));
Test 2:
drive.files.list({
media: {
mimeType: 'application/vnd.google-apps.folder'
}
}, function(err, data){
//I am getting all the data, the query is not working..
});
Test 3:
drive.files.list({
resource: {
mimeType: 'application/vnd.google-apps.folder'
}
}, function(err, data){
//This returns error not working at all!
});
You can check the drive.files.list function given here https://github.com/google/google-api-nodejs-client/blob/master/apis/drive/v2.js#L733 and use something like the following for it.
var drive = google.drive({ version: 'v2', auth: oauth2Client });
drive.files.list({
q='mimeType='image/jpg''
}, callback);
More details on the input parameters for the list function are on https://developers.google.com/drive/v2/reference/files/list

Basic file download example

I have been struggling my brain reading the nodejs documentation for google-apis.
I gathered a pretty long list of examples, but any of them helps me to do what I want to do. I just want to download a file from my drive using node js.
I have set up the OAUTH and I get an access token using this code (source: http://masashi-k.blogspot.com.es/2013/07/accessing-to-my-google-drive-from-nodejs.html )
var googleDrive = require('google-drive');
var GoogleTokenProvider = require("refresh-token").GoogleTokenProvider,
async = require('async'),
request = require('request'),
_accessToken;
var tokenProvider = new GoogleTokenProvider({
'refresh_token': REFRESH_TOKEN,
'client_id' : CLIENT_ID,
'client_secret': CLIENT_SECRET
});
tokenProvider.getToken(function(err, access_token) {
console.log("Access Token=", access_token);
_accessToken = access_token;
});
But I don't know how to continue from here. I tried with things like this with no luck:
function listFiles(token, callback) {
googleDrive(token).files().get(callback)
}
function callback(err, response, body) {
if (err) return console.log('err', err)
console.log('response', response)
console.log('body', JSON.parse(body))
}
listFiles(_accessToken,callback);
I feel like I'm very close, but I need some help here.
Thanks in advance.
There are two ways of doing that, depending on what you want to download. There is a big difference between downloading native Google Doc files and normal files:
Docs have to be downloaded using files.export API method, providing proper mime type to convert doc into
Normal files can be downloaded using files.get method, providing correct flag if you want to download file data instead of metadata
I'd suggest using GoogleApis NodeJS library (https://github.com/google/google-api-nodejs-client)
Initializing Drive API:
var Google = require('googleapis');
var OAuth2 = Google.auth.OAuth2;
var oauth2Client = new OAuth2('clientId','clientSecret','redirectUrl');
oauth2Client.setCredentials({
access_token: 'accessTokenHere'
refresh_token: 'refreshTokenHere'
});
var drive = Google.drive({
version: 'v3',
auth: this.oauth2Client
});
Importing file:
drive.files.get({
fileId: fileId,
alt: 'media' // THIS IS IMPORTANT PART! WITHOUT THIS YOU WOULD GET ONLY METADATA
}, function(err, result) {
console.log(result); // Binary file content here
});
Exporting native Google docs (you have to provide mime type for conversion):
drive.files.export({
fileId: fileId,
mimeType: 'application/pdf' // Provide mimetype of your liking from list of supported ones
}, function(err, result) {
console.log(result); // Binary file content here
});
Maybe it will help someone after so much time ;)
Take a look at the officially supported NodeJS client library for Google APIs at https://github.com/google/google-api-nodejs-client
The code required to get a file from Drive will be similar to that code at the bottom of the README used for inserting a file into Google Drive. You can also test your parameters to the API by using the API Explorer: https://developers.google.com/apis-explorer/#p/drive/v2/drive.files.get
Here's an example call to get a file from Google Drive:
client
.drive.files.get({ fileId: 'xxxx' })
.execute(function(err, file) {
// do something with file here
});

Resources