Richard Franek
Richard Franek

Reputation: 302

Node.js Google Drive api Download file error

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

Answers (4)

Akash Kumar Patel
Akash Kumar Patel

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

wcarhart
wcarhart

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

Richard Franek
Richard Franek

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

Tanaike
Tanaike

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.

Note :

  • For the googleapis after the version of v25.0.0, some bugs for APIs and the options are reported. I believe that these bugs are removed in the future. So if for APIs and the options you use, some errors occur, please modify the version of googleapis, and try again. The cases which were solved by modifying the version are as follows.

References :

If this was not useful for your situation, I'm sorry.

Edit :

How about this modification? In my environment, I confirmed that this modification worked by googleapis of v30.0.0.

From :

drive.files.get({fileId: fileId, alt: 'media'})
.on('end', () => {
    console.log('Done');
})
.on('error', err => {
    console.log('Error', err);
})
.pipe(dest);

To :

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

Related Questions