Search code examples
javascriptnode.jsgoogle-drive-apifsgoogle-api-nodejs-client

How to wait for file.get to download before moving on with Google Drive Api?


I am trying to download a file from Google Drive using the Google Drive API and it seems like I have one kind of implementation for it that I found in this post. With that being said, fs does not write to the file until after the program crashes. This leads me to believe that I can do some kind of async/await for the file to actually download but I'm not quite understanding where exactly.

I tried to make the callback function asynchronous and awaited the writeFile but it didn't seem to work.

imageHash.js

async function hasher() {
    ...
    ...
    ...
    for (let googImage of googlePosts) {
                const googleDownload = sharedFunc.downloadGoogle(googImage.id); //here is where it's supposed to download the image
                
                const hash1 = await imghash.hash('../images/options1.png', 8, 'binary'); //I download this image earlier on and is fine.
                
                const hash2 = await imghash.hash('../images/options2.jpg', 8, 'binary'); //code generates an error here
                
                const comp = await leven(hash1, hash2);
                
                console.log(comp);
                ...
                ...
                }
    ...
    ...
}

moduleExports.js

module.exports = {
    ...
    ...
    downloadGoogle: async (fileID) => {

        drive.files.get({fileId: fileID, alt: 'media'}, { responseType: "arraybuffer" },
            function(err, { data }) {
                fs.writeFile("../images/options2.jpg", Buffer.from(data), err => {
                    if (err) console.log(err);
                });
            }
        );

    },
    ...
    ...
}

I also tried using the image-downloader library with the Google Drive link because I'm able to easily access the file-id but it doesn't seem to download the image despite being given the direct url. If someone knows how to download an image using this library, I would accept that as an answer because I already know how to wait on the library to download the image.

If you need a sample image for this, you can use the one below

https://drive.google.com/uc?id=1ttF46_rexGt_ir2Wx-H9Oi58og4DGEYg


Solution

  • You can make the downloadGoogle function a promise function. More details can be found here. https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Promise

    Basically, you would have

    module.exports = {
        ...
        ...
        downloadGoogle: (fileID) => {
    
            return new Promise((resolve, reject) => { // make the function a promise
                drive.files.get({fileId: fileID, alt: 'media'}, { responseType: "arraybuffer" },
                function(err, { data }) {
                    fs.writeFile("../images/options2.jpg", Buffer.from(data), err => {
                        if (err) {
                            console.log(err);
                            return reject (err);
                        }
                        return resolve('file saved.')
                    });
                }
            );
            });
        },
        ...
        ...
    }
    

    Then you can call it like:

    const googleDownload = await sharedFunc.downloadGoogle(googImage.id); //here is where it's supposed to download the image