Reputation: 81
i am using nodejs , fastify , @fastify/multipart , fast-csv
to upload a csv file and get the data of it
so i made a plugin that takes files and get the data
but i tried to log the data its empty
using this code
instance.decorate('uploadCSV', async (parts: Multipart[]) => {
const uploads = parts.map(async (part: Multipart) => {
try {
if (part.file) {
const mimetype = part.mimetype;
const fileName = part.filename.split(' ').join('');
if (!fileName.toLowerCase().endsWith('.csv') || mimetype !== 'text/csv') {
throw instance.httpErrors.badRequest('file.not.csv');
}
const uploadDir = path.join(__dirname, 'uploads');
// Create the 'uploads' directory if it doesn't exist
if (!fs.existsSync(uploadDir)) {
fs.mkdirSync(uploadDir);
}
const filePath = path.join(uploadDir, fileName);
// Save the file directly using fs.promises.writeFile
await fs.promises.writeFile(filePath, part.file, 'utf-8');
// Parse the CSV file
const data = await new Promise<any[]>((resolve, reject) => {
const dataArray: any[] = [];
fs.createReadStream(filePath)
.pipe(csv.parse({ headers: true }))
.on('data', (row) => dataArray.push(row))
.on('end', () => resolve(dataArray))
.on('error', reject);
});
// Print the CSV data
console.log('CSV Data:', data);
// You can now do further processing with the parsed data
return { success: true, message: 'CSV file uploaded and processed successfully' };
}
} catch (error) {
throw error;
}
});
// Wait for all uploads to complete
await Promise.all(uploads);
});
tried to use it by
const { file } = request.body
await instance.uploadCSV(file)
and it always getting me
CSV Data: []
empty array
how to fix that
Upvotes: 0
Views: 780
Reputation: 199
I could not find what's exactly wrong with your code. However I have a working and better version of it.
my version of file upload will not stall event loop, because it is not doing any sync system calls.
You can take inspiration from following snippet:
import Fastify from 'fastify'
import multipart from '@fastify/multipart'
import fs from 'fs'
import util from 'util'
import { pipeline } from 'stream'
import csv from 'fast-csv';
import path from 'path'
const pump = util.promisify(pipeline)
export const app = Fastify({
logger: true
})
app.register(multipart);
app.decorate('uploadCsv', async function (parts) {
const folder = './uploads';
await createFolderIfMissing(folder);
for await (const part of parts) {
if (part.file) {
const destFilePath = path.join(folder, part.filename);
// upload and save the file
await pump(part.file, fs.createWriteStream(destFilePath));
console.log(await readCsv(destFilePath));
}
}
return { message: 'files uploaded' }
});
app.post('/upload', async function (req, reply) {
const parts = req.parts()
return app.uploadCsv(parts);
})
async function createFolderIfMissing(folderName) {
try {
await fs.promises.stat(folderName);
} catch (error) {
console.error("folder not found,.. creating..");
await fs.promises.mkdir(folderName);
}
}
function readCsv(filePath) {
// Parse the CSV file
return new Promise((resolve, reject) => {
const dataArray = [];
fs.createReadStream(filePath)
.pipe(csv.parse({ headers: true, delimiter: ";" }))
.on('data', (row) => dataArray.push(row))
.on('end', () => resolve(dataArray))
.on('error', reject);
});
}
const start = async () => {
try {
await app.listen({ port: 3000 })
console.log(`server listening on ${app.server.address().port}`)
} catch (err) {
app.log.error(err)
process.exit(1)
}
}
start()
Upvotes: 0