# #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 с заголовками, или у вас есть какие-либо другие ограничения для этого?