Проблема с созданием zip-файла в облачной функции Firebase

# #node.js #firebase #google-cloud-firestore #google-cloud-functions

Вопрос:

Я пытаюсь создать zip-файл строки в облачной функции Firebase. У меня есть куча документов в коллекции Firestore, и у каждого документа тоже есть подборка документов.Я пытаюсь перебрать документы, создающие строку (которая будет файлом csv), а затем вывести ее в сжатом файле. К сожалению, когда я запускаю функцию для создания zip-файла, она рано выходит из функции, доставляя сжатый файл, не содержащий соответствующей информации. Только начальные заголовки, которые находятся в файле csv.

Код функции Firebase cloud выглядит следующим образом:

     newApp.get('/createUtilCSV', (req, res) => {
        try {
            console.log("CreateAuditCSV started");
            const tempFilePath = path.join(os.tmpdir(), "Util_"   req.query.start   "---"   req.query.end   ".csv");
            console.log("Temp File Path: "   tempFilePath);
            let docRef = firestore.collection('utilisation');
            console.log("DocRef:"   docRef);
            var fromD = admin.firestore.Timestamp.fromDate(new Date(req.query.start));
            var toD = admin.firestore.Timestamp.fromDate(new Date(req.query.end));
            console.log("from date: ", fromD);
            console.log("to date: ", toD);
            docRef.where("timestamp", ">=", fromD).where("timestamp", "<=", toD).get().then(snapshot => {
                var output = fs.createWriteStream(tempFilePath);
                var archive = archiver('zip', {
                    gzip: true,
                    zlib: {
                        level: 9
                    } // Sets the compression level.
                });
                console.log("Snapshot:"   snapshot.size);
                var utilText = "App Version,Author,Building,City,Country,Date,Floor ID,Floor Name, Floor Region,Bookable,Business Unit,Capacity,Fixed,Furniture Height,Occupancy,Position X,Position Y,Restricted,Status Date,Status Type,Unique Ref,Workspace Type,Report IDn";
                let utils = snapshot.docs;
                console.log("Snapshot count:"   snapshot.capacity);
                utils.forEach(doc => {
                    var line = doc.data();
                    var utilLine = "";
                    utilLine = utilLine   line.appVersion   ",";
                    utilLine = utilLine   line.authorEmail   ",";
                    utilLine = utilLine   line.building   ",";
                    utilLine = utilLine   line.city   ",";
                    utilLine = utilLine   line.country   ",";
                    utilLine = utilLine   line.timestamp.toDate()   ",";
                    utilLine = utilLine   line.floorId   ",";
                    utilLine = utilLine   line.floorName   ",";
                    utilLine = utilLine   line.region   ",";
                    var utilisationCollection = firestore.collection('utilisation').doc(line.documentID).collection('workspaces');
                    utilisationCollection.get().then(snap => {
                        let workspaces = snap.docs;
                        workspaces.forEach(space => {
                            var lineSpace = space.data();
                            var spaceAdd = utilLine;
                            spaceAdd = spaceAdd   lineSpace.bookable   ",";
                            spaceAdd = spaceAdd   lineSpace.businessUnit   ",";
                            spaceAdd = spaceAdd   lineSpace.capacity   ",";
                            spaceAdd = spaceAdd   lineSpace.fixed   ",";
                            spaceAdd = spaceAdd   lineSpace.height   ",";
                            spaceAdd = spaceAdd   lineSpace.occupancy   ",";
                            spaceAdd = spaceAdd   lineSpace.positionX   ",";
                            spaceAdd = spaceAdd   lineSpace.positionY   ",";
                            spaceAdd = spaceAdd   lineSpace.restricted   ",";
                            spaceAdd = spaceAdd   lineSpace.statusDate.toDate()   ",";
                            spaceAdd = spaceAdd   lineSpace.statusType   ",";
                            spaceAdd = spaceAdd   lineSpace.uniqueRef   ",";
                            spaceAdd = spaceAdd   lineSpace.workspaceType   ",";
                            spaceAdd = spaceAdd   line.documentID   "n";
                            console.log("SpaceAdd: "   spaceAdd);
                            utilText = utilText   spaceAdd;
                        });
                    });
                });
                try {
                    // listen for all archive data to be written
                    // 'close' event is fired only when a file descriptor is involved
                    output.on('close', function() {
                        console.log(archive.pointer()   ' total bytes');
                        console.log('archiver has been finalized and the output file descriptor has closed.');
                        console.log("Util Text: ", utilText);
                        bucket.upload(tempFilePath, {
                            make_public: true,
                            gzip: true,
                            destination: tempFilePath,
                            metadata: metadata,
                        });
                        //Let's get the signed URL
                        const file = admin.storage().bucket().file(tempFilePath);
                        console.log('File: '   file);
                        var expiryDate = new Date();
                        expiryDate.setDate(expiryDate.getDate()   1);
                        file.getSignedUrl({
                            action: 'read',
                            expires: expiryDate
                        }).then(urls => {
                            const signedUrl = urls[0];
                            console.log('Send: '   signedUrl);
                            res.redirect(signedUrl);
                            res.end();
                        });
                    });
                    output.on('end', function() {
                        console.log('Data has been drained');
                    });
                    // good practice to catch warnings (ie stat failures and other non-blocking errors)
                    archive.on('warning', function(err) {
                        if(err.code === 'ENOENT') {
                            // log warning
                        } else {
                            // throw error
                            throw err;
                        }
                    });
                    // good practice to catch this error explicitly
                    archive.on('error', function(err) {
                        throw err;
                    });
                    const metadata = {
                        contentType: "application/zip",
                    };
                    archive.pipe(output);
                    // append a file from string
                    archive.append(utilText, {
                        name: tempFilePath
                    });
                    archive.finalize();
                    console.log("tempFilePath: "   tempFilePath);
                    console.log("Export Util CSV finished");
                } catch(err) {
                    console.log(err);
                }
            }).catch(err => console.log(err));
        } catch(error) {
            console.log("Export error:"   error);
        }
    });
 

Комментарии:

1. Подходит ли экспортная операция для ваших нужд?

2. Нет, Фрэнк, мне нужно создать очень конкретный csv-файл, и, насколько я знаю, операция экспорта не совсем это сделает.

3. Экспорт из gcloud может быть --collection-ids флагом, который вы можете использовать для выбора экспортируемых коллекций, можете ли вы указать, связано ли ограничение csv с заголовками, или у вас есть какие-либо другие ограничения для этого?