Reputation: 302
This is my code:
const fs = require('fs');
const { google } = require('googleapis');
const Auth = require('../authorization/auth_drive/auth');
// get data
var gotData = function downloadFiles(fileId, callback) {
let content = fs.readFileSync('./GEARS/authorization/client_secret.json');
Auth(JSON.parse(content), (auth) => {
//const returnData = [];
const drive = google.drive({ version: 'v3', auth });
const fileId = '';
const dest = fs.createWriteStream('./test_files/test.png');
drive.files.get({fileId: fileId, alt: 'media'})
.on('end', () => {
console.log('Done');
})
.on('error', err => {
console.log('Error', err);
})
.pipe(dest);
});
};
module.exports = gotData;
Following the google documentation LINK
All other functions I have tried, like List, Copy, Upload or Sheets Read&Write work perfectly for me, except for the Download. My application instantly crashes with the error
TypeError: Cannot read property 'on' of undefined
I have looked at Google's Sample of this very functionality, and I have not found anything that differs, so why does it work for Google Developers, while for me it doesn't?
I have not found a single person with this problem on google, so maybe, if you understand what should be done, you can see what I am doing wrong.
-- I will include THIS LINK, that is a Copy function I have, which works perfectly, in case it would be relevant.
Thanks for any advice.
Upvotes: 6
Views: 9003
Reputation: 11
I am using Google drive Api and created google docs file. which is stored in google drive. Now i want to export this google docs in MS word Document in Nodejs. for which I used google drive export file api which is returning data in Byte as mentioned in google drive developer official website Google Drive Export File. But I want bytes data in doc/docx file. So I tried so many things and finally I got solution and now it is working fine.
Now I am able to download google docs in any types of file... In this code I am exporting data in MS wordDocument But If you want download "docs" in another types of file then just change "mimeType" for that just checkout mimeType Formats. And also change creating file "Extention" (resume.docx)
const fs = require('fs');
const { google } = require('googleapis');
const ROOT = require('path').resolve("./")
const Export = async (file_id = '13izcbyZ_eUhY6y6Ac_pYsR0Hip2vaP8WZ4stizsjfR4') => {
try {
// Authenticate with google service account
const auth = new google.auth.GoogleAuth({ // Scopes can be specified either as an array or as a single, space-delimited string.
keyFile: `${ROOT}/credential.json`,
scopes: ['https://www.googleapis.com/auth/documents', 'https://www.googleapis.com/auth/drive', 'https://www.googleapis.com/auth/drive.file',]
});
// Acquire an auth client, and bind it to all future calls
const authClient = await auth.getClient();
google.options({auth: authClient});
const drive = google.drive({version: 'v3'});
let progress = 0;
// Set the location For store export file
var dest = await fs.createWriteStream(ROOT + "/public/merge/resume.docx");
// Calling google drive export api
let resp = await drive.files.export({
fileId: file_id,
mimeType: "application/vnd.openxmlformats-officedocument.wordprocessingml.document"
}, {responseType: 'stream'});
resp.data.on('end', function () {
console.log('Done');
}).on('error', function (err) {
console.log('Error during download', err);
}).on('data', d => {
progress += d.length;
if (process.stdout.isTTY) {
process.stdout.clearLine();
process.stdout.cursorTo(0);
process.stdout.write(`Downloaded ${progress} bytes`);
}
}).pipe(dest)
let DownloadURL = "localhost:3001/merge/resume.docx";
return DownloadURL;
} catch (err) {
console.log("err........", err)
}
}
Upvotes: 1
Reputation: 2783
Just to add onto @Tanaike's answer, here is a promisified version in case someone else arrives here looking for such (like myself):
await new Promise((resolve, reject) => {
drive.files.get(
{fileId: image.id, alt: 'media'},
{responseType: 'stream'},
(err, res) => {
res.data.on('end', () => resolve()).on('error', () => reject()).pipe(dest)
}
)
})
Upvotes: 0
Reputation: 302
I have altered Google's example. This way it works:
const fs = require('fs');
const { google } = require('googleapis');
const Auth = require('../authorization/auth_drive/auth');
// get data
var gotData = function downloadFiles(fileId, destination, callback) {
let content = fs.readFileSync('./GEARS/authorization/client_secret.json');
Auth(JSON.parse(content), (auth) => {
const returnData = [];
const drive = google.drive({ version: 'v3', auth });
const file = fs.createWriteStream(destination); // destination is path to a file
drive.files.get(
{fileId: fileId, alt: 'media',},
{responseType: 'stream'}, (err, res ) => {
if (err) {
returnData.push(["ERR"]);
returnData.push("" + err);
} else {
res.data.pipe(file);
returnData.push("Downloaded");
}
callback(returnData);
});
});
};
module.exports = gotData;
Upvotes: 4
Reputation: 201378
From your script, I thought that you may be using the googleapis of the version more than v24.0.0. So how about modifying the version of googleapis? Also I have experienced the same issue with your situation. In my case, the issue was removed by modifying the version of googleapis to v24.0.0.
When I used v25.0.0 - v30.0.0 of googleapis, the error occurs. When it used the googleapis of v24.0.0, the error was removed.
If this was not useful for your situation, I'm sorry.
How about this modification? In my environment, I confirmed that this modification worked by googleapis of v30.0.0.
drive.files.get({fileId: fileId, alt: 'media'})
.on('end', () => {
console.log('Done');
})
.on('error', err => {
console.log('Error', err);
})
.pipe(dest);
drive.files.get({fileId: fileId, alt: 'media'}, {responseType: 'stream'},
function(err, res){
res.data
.on('end', () => {
console.log('Done');
})
.on('error', err => {
console.log('Error', err);
})
.pipe(dest);
}
);
Upvotes: 9