2

I am trying to read the csv file inside the Firebase functions so that i can send the mail to the all the records. I am planning to go with the following procedure

  1. upload the csv
  2. fire a on finalize function
  3. read the file and send emails

Below is the function

import * as functions from "firebase-functions";
import * as mkdirp from "mkdirp-promise";
import * as os from "os";
import * as path from "path";
import csv = require('csvtojson');

const gcs = require('@google-cloud/storage')({ keyFilename: 'service-account-credentials.json' });
const csvDirectory = "csv";
export = functions.storage.object().onFinalize(async (object) => {
    const filePath = object.name;
    const contentType = object.contentType;
    const fileDir = path.dirname(filePath);

    if(fileDir.startsWith(csvDirectory) && contentType.startsWith("text/csv")) {
        const bucket = gcs.bucket(object.bucket);
        const file = bucket.file(filePath);
        const fileName = path.basename(filePath);
        const tempLocalFile = path.join(os.tmpdir(), filePath);
        const tempLocalDir = path.dirname(tempLocalFile);
        console.log("values", bucket, file, fileName, tempLocalDir, tempLocalFile);
        console.log("csv file uploadedeeeed");
        await mkdirp(tempLocalDir);
        await bucket.file(filePath).download({
           destination: tempLocalFile
        });
        console.log('The file has been downloaded to', tempLocalFile);
        csv()
           .fromFile(tempLocalFile)
           .then((jsonObj) => {
              console.log(jsonObj);
           })
    }
});

While running the code i am only getting csv file uploadeded which i have written inside the console.log and then i get the timeout after 1 minute .i am also not getting the The file has been downloaded to log . Can anybody look at the code and help me to get out of this.

Renaud Tarnec
  • 79,263
  • 10
  • 95
  • 121
Night owl
  • 145
  • 10

1 Answers1

1

You are mixing up the use of async/await together with a call to then() method. You should also use await for the fromFile() method.

The following should do the trick (untested):

export = functions.storage.object().onFinalize(async (object) => {
    const filePath = object.name;
    const contentType = object.contentType;
    const fileDir = path.dirname(filePath);

    try {
            if (fileDir.startsWith(csvDirectory) && contentType.startsWith("text/csv")) {
                //.....
                await mkdirp(tempLocalDir);
                await bucket.file(filePath).download({
                    destination: tempLocalFile
                });
                console.log('The file has been downloaded to', tempLocalFile);

                const jsonObj = await csv().fromFile(tempLocalFile);
                console.log(jsonObj);
                return null;

             } else {
                //E.g. throw an error
             }


    } catch (error) {
        //.....
    } 

});

Also note that (independently of the mixed use of async/await and then()), with the following line in your code

csv().fromFile(tempLocalFile).then(...)

you were not returning the Promise returned by the fromFile() method. This is a key point in Cloud Functions.

I would suggest you watch the official Video Series on Cloud Functions (https://firebase.google.com/docs/functions/video-series/) and in particular the videos on Promises titled "Learn JavaScript Promises".

Renaud Tarnec
  • 79,263
  • 10
  • 95
  • 121