I have a problem in uploding pdf file from from fontend in Nodejs so the problem is how to convert file type to correct form to upload to google drive
my file type is like this
{ fieldname: 'file',
originalname: 'test.pdf',
encoding: '7bit',
mimetype: 'application/pdf',
buffer:
and my code is like this
` const {google} = require('googleapis')
const drive = google.drive('v3')
const app = express()
const upload = multer()
app.post(
'test-upload-pdf-file',
upload.single('file'),
(req, res, next) => {
drive.files.create({
resource: { mimeType: 'application/pdf'},
media: {mimeType: 'application/pdf', body: req.file.buffer},
fields: 'id'
}, function (err, file) {
}
)`
Hi, @Thammawat I did it the following way. It worked for me. Let me know if it works for you.
app.post('/upload', upload.single('my file'), (req, res, next) => {
let stream = require('stream');
let fileObject = req.file;
let bufferStream = new stream.PassThrough();
bufferStream.end(fileObject.buffer);
google.drive({ version: 'v3', auth: oauth2Client })
.files.create({
media: {
mimeType: 'application/pdf',
body: bufferStream
},
'requestBody': {
'name': 'test.pdf',
mimeType: 'application/pdf',
},
fields: 'id',
}).then(function (resp) {
console.log(resp,'resp');
}).catch(function (error) {
console.log(error);
})
res.send(`File uploaded`);
});
Is there any sample code? I searched but cannot find. @JustinBeckwith
@Thammawat
modifying code snippet of @vishald123's answer,
requestBody is resource (mimeType should be removed from it, parents can be added to store the file/folder in a specific folder.)
refactored code is right here. Source:
app.post('/upload', upload.single('my file'), (req, res, next) => {
const { google } = require('googleapis');
const stream = require('stream');
// const serviceAccount = 'PATH TO SERVICE ACCOUNT';
let fileObject = req.file;
let bufferStream = new stream.PassThrough();
bufferStream.end(fileObject.buffer);
// const jWTClient = new google.auth.JWT(
// serviceAccount.client_email,
// null,
// serviceAccount.private_key,
// ['<COMMA SEPARATED SCOPES WHICH ARE AUTHORIZED>']
// )
google.drive({ version: 'v3'})
.files.create({
auth: oauth2Client/jWTClient,
media: {
mimeType: 'application/pdf',
body: bufferStream
},
resource: {
name: 'test.pdf',
// if you want to store the file in the root, remove this parents
parents: ['folder id in which he file needs to be stored.']
},
fields: 'id',
}).then(function (resp) {
console.log(resp,'resp');
}).catch(function (error) {
console.log(error);
})
res.send('File uploaded');
});
Reference to have a look: https://developers.google.com/drive/api/v3/manage-uploads#simple
Also, make sure that you're using nodeJS 10.x.x as previous versions will cause issues in stream
Let me know if it doesn't works for you.
@Thammawat
modifying code snippet of @vishald123's answer,
requestBody is resource (mimeType should be removed from it, parents can be added to store the file/folder in a specific folder.)
refactored code is right here. Source:app.post('/upload', upload.single('my file'), (req, res, next) => { const { google } = require('googleapis'); const stream = require('stream'); // const serviceAccount = 'PATH TO SERVICE ACCOUNT'; let fileObject = req.file; let bufferStream = new stream.PassThrough(); bufferStream.end(fileObject.buffer); // const jWTClient = new google.auth.JWT( // serviceAccount.client_email, // null, // serviceAccount.private_key, // ['<COMMA SEPARATED SCOPES WHICH ARE AUTHORIZED>'] // ) google.drive({ version: 'v3'}) .files.create({ auth: oauth2Client/jWTClient, media: { mimeType: 'application/pdf', body: bufferStream }, resource: { name: 'test.pdf', // if you want to store the file in the root, remove this parents parents: ['folder id in which he file needs to be stored.'] }, fields: 'id', }).then(function (resp) { console.log(resp,'resp'); }).catch(function (error) { console.log(error); }) res.send('File uploaded'); });
Reference to have a look: https://developers.google.com/drive/api/v3/manage-uploads#simple
Also, make sure that you're using nodeJS 10.x.x as previous versions will cause issues in streamLet me know if it doesn't works for you.
Hi, I'm able to upload successfully but I can't seem to find the image in my google drive. I'm not sure where my image is uploaded to.
@helloitsm3
If you have provided resource.parents the file should have been uploaded to the directory of the id provided. Or else it will be uploaded to the root directory.
I rather suggest, to look into the Quick Access section of Google Drive
If you have provided resource.parents the file should have been uploaded to the directory of the id provided. Or else it will be uploaded to the root directory.
I rather suggest, to look into the Quick Access section of Google Drive
I tried that. It's not showing up. However, the funny thing is that I am able to get all the images when I try to use google.drive.files.list(). Could it be because I'm using a g_service account?
@helloitsm3 Can you please provide the argument that you provided in google.drive.files.list?
@helloitsm3 Can you please provide the argument that you provided in google.drive.files.list?
const auth = new google.auth.JWT({
email: privateKey.client_email,
key: privateKey.private_key,
scopes: ["https://www.googleapis.com/auth/drive"]
});
google.drive({ version: "v3" }).files.list(
{
auth: auth,
q: "mimeType='image/jpeg'",
fields: "nextPageToken, files(id, name)",
spaces: "drive",
pageToken: pageToken
})
@helloitsm3 I would like to see auth definition.
@helloitsm3 I would like to see auth definition.
I included it
In this case,
search in google drive
owner: privateKey.client_email(put the value) and search.
owner: privateKey.client_email(put the value)
Nope. It's completely empty. There's nothing at all.
Try this.
const auth = new google.auth.JWT(
accountKey.client_email,
null,
accountKey.private_key,
["https://www.googleapis.com/auth/drive"],
'YOUR EMAIL ID'
);
Try this.
const auth = new google.auth.JWT( accountKey.client_email, null, accountKey.private_key, ["https://www.googleapis.com/auth/drive"], 'YOUR EMAIL ID' );
Doesn't seem to work. My email ID returns an error. "Client is unauthroized to retrieve access tokens using this method, or client not authrozied for any of the scopes requested".
Are you using G-Suit email id or your personal email ID?
Try this.
const auth = new google.auth.JWT( accountKey.client_email, null, accountKey.private_key, ["https://www.googleapis.com/auth/drive"], 'YOUR EMAIL ID' );
Could it be because I'm using a private key that's link to my service account? Meaning my service account has it's own drive instead of my main account?
Are you using G-Suit email id or your personal email ID?
my personal email ID which I use to create the service account
Service Account does not own Google Drive. It can act as a user. Like you can share a file/folder with the client_email mentioned in service account, It can own a file/folder but not Drive.
Since you are using personal email id,
Try this
resource.parents
having value [ID of the folder].URL format of a directory in Google Drive
https://drive.google.com/drive/folders/0B-ExmsZGdWssSWluUkZQb0pWd2M
then the ID will be 0B-ExmsZGdWssSWluUkZQb0pWd2M
Code snippet
google.drive({ version: 'v3'})
.files.create({
auth: oauth2Client/jWTClient,
media: {
mimeType: 'application/pdf',
body: bufferStream
},
resource: {
name: 'test.pdf',
// if you want to store the file in the root, remove this parents
parents: ['0B-ExmsZGdWssSWluUkZQb0pWd2M'] // ID of the folder that you created.
},
fields: 'id',
}).then(function (resp) {
console.log(resp,'resp');
}).catch(function (error) {
console.log(error);
})
Service Account does not own Google Drive. It can act as a user. Like you can share a file/folder with the private key mentioned in service account, It can own a file/folder but not Drive.
Since you are using personal email id,
Try this1. Create a folder in Drive. 2. Share the folder with the private key of the service account. 3. Upload your files providing `resource.parents` having value [ID of the folder]. You can get the id of the folder from the URL.
URL format of a directory in Google Drive
https://drive.google.com/drive/folders/0B-ExmsZGdWssSWluUkZQb0pWd2M
then the ID will be 0B-ExmsZGdWssSWluUkZQb0pWd2MCode snippet
google.drive({ version: 'v3'}) .files.create({ auth: oauth2Client/jWTClient, media: { mimeType: 'application/pdf', body: bufferStream }, resource: { name: 'test.pdf', // if you want to store the file in the root, remove this parents parents: ['0B-ExmsZGdWssSWluUkZQb0pWd2M'] }, fields: 'id', }).then(function (resp) { console.log(resp,'resp'); }).catch(function (error) { console.log(error); })```
OMG! It works. Thank you very much.
Good to know.
Keep up doing Interesting things!
Good to know.
Keep up doing Interesting things!
Hi, I'm running into another issue when uploading images via React Native. I appended the image to FormData and tried to send the image to google cloud storage but it keeps giving me "No such object" error.
It sounds like the approach outlined by @vishald123 works for folks :+1:
@helloitsm3 could I bother you to open another issue on the topic of Cloud Storage/React? I think you should be able to use the nodejs-cloud-storage library's signed URL API (potentially).
Thanh you very much!!!
It sounds like the approach outlined by @vishald123 works for folks 馃憤
@helloitsm3 could I bother you to open another issue on the topic of Cloud Storage/React? I think you should be able to use the nodejs-cloud-storage library's signed URL API (potentially).
Thank you. I'll give it a try first before I open a new issue
I tried following the methods mentioned above and followed the code almost to the letter, but for some reason I'm still unable to get this thing to work.
Here's my code:
var {google} = require('googleapis');
const { GoogleAuth } = require('google-auth-library');
const stream = require('stream');
const serviceAccount = require('../config/node-uploader-99-9e3f13fd0cde.json')
console.log(serviceAccount);
let fileObject = req.body.filePDF;
console.log(fileObject);
let bufferStream = new stream.PassThrough();
bufferStream.end(fileObject.buffer);
const jWTClient = new google.auth.JWT(
serviceAccount.client_email,
null,
serviceAccount.private_key,
['https://www.googleapis.com/auth/drive', 'https://www.googleapis.com/auth/drive.file']
)
google.drive({ version: 'v3'})
.files.create({
auth: GoogleAuth/jWTClient,
media: {
mimeType: 'application/pdf',
body: bufferStream
},
resource: {
name: 'DeniTheFile.pdf',
// if you want to store the file in the root, remove this parents
parents: ['1KwLSHyu9R1jo3-ahtWgJCohoCsrtrE-I']
},
fields: 'id',
}).then(function (resp) {
console.log(resp,'resp');
}).catch(function (error) {
console.log(error);
})
res.send('File uploaded');
});
The odd part is that when I try an upload I get a "File uploaded" success message, but the file is nowhere to be found on my Drive.
Does anyone have any suggestions on what I might be missing ?
I tried following the methods mentioned above and followed the code almost to the letter, but for some reason I'm still unable to get this thing to work.
Here's my code:
var {google} = require('googleapis'); const { GoogleAuth } = require('google-auth-library'); const stream = require('stream'); const serviceAccount = require('../config/node-uploader-99-9e3f13fd0cde.json') console.log(serviceAccount); let fileObject = req.body.filePDF; console.log(fileObject); let bufferStream = new stream.PassThrough(); bufferStream.end(fileObject.buffer); const jWTClient = new google.auth.JWT( serviceAccount.client_email, null, serviceAccount.private_key, ['https://www.googleapis.com/auth/drive', 'https://www.googleapis.com/auth/drive.file'] ) google.drive({ version: 'v3'}) .files.create({ auth: GoogleAuth/jWTClient, media: { mimeType: 'application/pdf', body: bufferStream }, resource: { name: 'DeniTheFile.pdf', // if you want to store the file in the root, remove this parents parents: ['1KwLSHyu9R1jo3-ahtWgJCohoCsrtrE-I'] }, fields: 'id', }).then(function (resp) { console.log(resp,'resp'); }).catch(function (error) { console.log(error); }) res.send('File uploaded'); });
The odd part is that when I try an upload I get a "File uploaded" success message, but the file is nowhere to be found on my Drive.
Does anyone have any suggestions on what I might be missing ?
It seems like "File uploaded" message will always print out regardless of the status. Shouldn't you res.send once you've successfully uploaded the file in the promise?
Hey Sean, I does print regardless of the outcome indeed. I checked the status code on the response and it's a 200. Turns out the uploads are happening, but they are happening on the "service account' and I wanted to be able to check them out on the GDrive Dashboard.
@deniivanov
To check the file out on G-Drive dashboard, refer my answer
https://github.com/googleapis/google-api-nodejs-client/issues/1633#issuecomment-509663581
Made some tweeks to the authorization on both Google's side and the code's side and it finally worked! Thanks @HiteshSalavi !
Most helpful comment
Hi, @Thammawat I did it the following way. It worked for me. Let me know if it works for you.