У меня был аналогичный запрос на обработку CSV-файла, и я попытался реализовать ваше решение: оно работает, но пока я использовал его с журналом консоли. Я попытался сохранить переменную «запись» в массиве с именем «результаты», но я только что получил пустой массив [], и после представления этого пустого массива я получил ответ console.log, представляющий проанализированные данные CSV.
Так что, похоже, это вопрос синхронизации. Я имею в виду, что обработка CSV-файла занимает некоторое время. Поэтому я попытался сжать ваш код и преобразовать его в обещание, а затем выполнить его. Итак, после выполнения обещания мой массив был готов к использованию.
- Примечание: я новичок, поэтому могут быть ошибки. До сих пор это работает нормально для меня.
- Примечание. Содержимое моего тестового CSV-файла:
title, type, value, category
Loan, income, 1500, Others
Website Hosting, outcome, 50, Others
Ice cream, outcome, 3, Food
Примечание: есть некоторые отличия от вашего случая: я получаю один единственный файл из каталога '/import. Я использую приложение Insomnina Designer для отправки тела составной формы с одним файлом с именем importFile.
Примечание. Я импортировал те же библиотеки, что и вы, а также использовал концепцию промежуточного программного обеспечения.
Примечание. В этом случае я просто ожидал один файл, поэтому использовал multer({dest: './upload'}).single('importFile'). Его также можно использовать .any().
Примечание. Я использую машинописный текст, поэтому для JS это просто вопрос удаления после объявления некоторой переменной :@type, например
Примечание: я оставил вариант 1 — работа только с массивами и вариант 2 — использование объектов.
const results: object[] = [];
becomes:
const results = [];
Переходим к коду:
import { Router, Request, Response } from 'express';
import csv from 'csv-parse';
import multer from 'multer';
import fs from 'fs';
// used on option 2 due typescript
interface CSVTransactionDTO {
title: string;
value: number;
type: 'income' | 'outcome';
category: string;
}
app.post(
'/import', // route name
multer({ dest: './upload' }).single('importFile'), // middleware to download one file (csv)
async (request: Request, response: Response) => {//last middleware with CSV parsing with arrow function
const filePath = request.file.path;
let rowCounter = 0;
const results: string[] = [];// option 1
const newTransactions: CSVTransactionDTO[] = [];// option 2
function parseCSVPromise(): Promise<void> {
return new Promise((resolve, reject) => {
const ConfigCSV = {
// delimiter:';',//other delimiters different from default = ','
from_line: 2, // data starts here
trim: true, // ignore white spaces immediately around the delimiter (comma)
};
fs.createReadStream(filePath)
.pipe(csv(ConfigCSV))
.on('data', /* async */ row => {
rowCounter += 1;// counter of how many rows were processed
// console.log(data); // just test
results.push(row); // Option1 - The simplest way is to push a complete row
const [title, type, value, category] = row;// Option2, process it as an object
newTransactions.push({title, type, value, category});// Option2, process it as an object
})
.on('error', error => {
reject(error);
throw new Error('Fail to process CSV file');
})
.on('end', () => {
resolve();// ends the promise when CSV Parse send 'end' flag
});
});
}
await parseCSVPromise(); // now using the created promise - await finishing parsingCSV
console.log('option1', results);// option1
console.log('option2',newTransactions);// option2
return response.json({ resultsCounter, results }); // For testing only - interrupting the rote execution
// continue processing results and send it to dataBase...
//await fs.promises.unlink(filePath); // optionally you can delete the file parsed/processed
вариант 1 ответ:
[
[ 'Loan', 'income', '1500', 'Others' ],
[ 'Website Hosting', 'outcome', '50', 'Others' ],
[ 'Ice cream', 'outcome', '3', 'Food' ]
]
Вариант 2 ответа:
[
{ title: 'Loan', type: 'income', value: '1500', category: 'Others' },
{ title: 'Website Hosting', type: 'outcome', value: '50', category: 'Others' },
{ title: 'Ice cream', type: 'outcome', value: '3', category: 'Food' }
]
person
Ramon Menezes
schedule
06.10.2020