Reputation: 195
I need to get a CSV file from firebase storage, then parse it so I can send data to the right documents in firestore. I had a working function, but I don't know why. This is the code that should parse the CSV data. Currently, I get undefined in the data constant, so I think the data from the csv gets converted to utf8 incorrectly. However, it used to run before.
exports.importCSVAppointments = functions.region('europe-west3').storage.object().onFinalize((object) => {
const name = object.name;
//Test if file is in correct folder and is csv file
const nameSplit = name.split('/');
const organisation = nameSplit[1].split('_')[1];
const folder = nameSplit[0];
if(folder == 'imports'){
//Retrieve the file from firebase storage
const storage = new Storage();
const bucket = storage.bucket('gs://fmis-online-dev.appspot.com');
admin.storage().bucket().file(name)
.download(function (err, contents) {
if (!err) {
const convert = (from, to) => str => Buffer.from(str, from).toString(to);
const hexToUtf8 = convert('hex', 'utf8');
const data = hexToUtf8(contents);
const dataSplit = data.split('\n');
console.log(dataSplit);
for(i=1;i<=dataSplit.length-1;i++){
console.log('actually runs');
//This will run for every appointment
//Get appointment data
const text = dataSplit[i];
const parsedData = text.match( /\s*(\".*?\"|'.*?'|[^,]+)\s*(,|$)/g ).map( function (text) {
let m;
if (m = text.match(/^\s*\"(.*?)\"\s*,?$/)) return m[1]; // Double Quoted Text
if (m = text.match(/^\s*'(.*?)'\s*,?$/)) return m[1]; // Single Quoted Text
if (m = text.match(/^\s*(true|false)\s*,?$/)) return m[1] === "true"; // Boolean
if (m = text.match(/^\s*((?:\+|\-)?\d+)\s*,?$/)) return parseInt(m[1]); // Integer Number
if (m = text.match(/^\s*((?:\+|\-)?\d*\.\d*)\s*,?$/)) return parseFloat(m[1]); // Floating Number
if (m = text.match(/^\s*(.*?)\s*,?$/)) return m[1]; // Unquoted Text
return text;
} );
console.log(parsedData);
This is the CSV file that needs to be parsed. The first row is always the title
subject,contactName,contactEmail,contactPhoneNumber,dateStart,dateEnd,timeStart,timeEnd,isRecurring,frequency,days,location,room,visitorType,visitorName,visitorPhoneNumber,visitorEmail,licensePlate,sendInvite
Test CSV,name,[email protected],+31 6 12345678,26-2-2021,26-2-2021,12:00,13:00,no,,"[]",Katrien NV,2A,Cursist,Dr. Doofenschmirtz,+31 6 98765432,[email protected],,no
Upvotes: 0
Views: 1028
Reputation: 83093
Since this code is executed in a Cloud Function, you should use the "promise version" of the asynchronous download()
method, as follows:
if (folder == 'imports') {
//Retrieve the file from firebase storage
const storage = new Storage();
const bucket = storage.bucket('gs://fmis-online-dev.appspot.com');
return admin.storage().bucket().file(name). // <==!!! see the return here
.download()
.then(data => {
const contents = data[0];
// ....
return null; // <==!!! see the return here
})
.catch(error => {
// ....
return null; // <==!!! see the return here
})
} else {
return null; // <==!!! see the return here
}
You'll find in the doc the explanation on why it is important to return a Promise, in order to correctly manage the life cycle of the Cloud Function.
You don't show how you write to Firestore, but you must include in the Promises chain the Promises returned by the asynchronous Firestore methods, e.g.:
return admin.storage().bucket().file(name). // <==!!! see the return here
.download()
.then(data => {
const contents = data[0];
// ....
const parsedData = ....
return admin.firestore() // <==!!! see the return here
.doc('xxx/yyyy').set( { parsedData, foo: bar });
})
.catch(error => {
// ....
return null; // <==!!! see the return here
})
Upvotes: 2