Zenixo
Zenixo

Reputation: 877

How do I read an uploaded file (text/.csv) using nestjs and Multer

I need to read my CSV file in the controller to add CSV file data into my DB. But I don't know the way to that. I search for an answer so many times but I can't find an answer to related my question. I really need your help with this. Thank you.

My Controller method :-

  @Post()
  @UseInterceptors(FileInterceptor('filename', { dest: './uploads' }))
  async upload(@UploadedFile() files: Express.Multer.File) {
    console.log(files);
  }

My console log output:-

enter image description here

Upvotes: 3

Views: 11755

Answers (1)

ferozpuri
ferozpuri

Reputation: 386

I have just finished with an exactly similar scenario. First I uploaded csv file to my uploads/csv directory with the name 'data.csv'

I am using this library for parsing data into JSON

https://www.npmjs.com/package/nest-csv-parser

Here is core to my controller file.

@Post('upload')
  @UseInterceptors(FileInterceptor('file', {
    storage: diskStorage({
      destination: './uploads/csv',
      filename: csvFileName,
    }),
    fileFilter: csvFileFilter,
  }))
  uploadFile(@UploadedFile() file: Express.Multer.File) {
    const response = {
      message: "File uploaded successfully!",
      data: { 
        originalname: file.originalname,
        filename: file.filename,
      }
    };
    return response;
  }

Here is a code for my component app.module.ts

import { Module } from '@nestjs/common';
import { TypeOrmModule } from '@nestjs/typeorm';
import { Coin } from './coin.entity';
import { CoinsController } from './coins.controller';
import { CoinsService } from './coins.service';
import {CsvModule} from "nest-csv-parser";
import {MulterModule} from "@nestjs/platform-express";

@Module({
  imports: [
    TypeOrmModule.forFeature([Coin]),
      CsvModule,
    MulterModule.register({
      dest: './uploads/csv',
    }),
  ],
  controllers: [
    CoinsController,
  ],
  providers: [CoinsService]
})
export class CoinsModule { }

I've also created on utils or a helper file where I am having all csv created logic

import {extname, join} from 'path';

export const csvFileFilter = (req, file, callback) => {
    if (!file.originalname.match(/\.(csv)$/)) {
        return callback(new Error('Only CSV files are allowed!'), false);
    }
    callback(null, true);
};

export const csvFileName = (req, file, callback) => {
    //const name = file.originalname.split('.')[0];
    const fileExtName = extname(file.originalname);
    callback(null, `data${fileExtName}`);
};

export const getCSVFile = () => {
    //const name = file.originalname.split('.')[0];
    const filePath = join(__dirname, "..", "..", "uploads/csv", "data.csv");
    return filePath;
};

export const editFileName = (req, file, callback) => {
    const name = file.originalname.split('.')[0];
    const fileExtName = extname(file.originalname);
    const randomName = Array(4)
        .fill(null)
        .map(() => Math.round(Math.random() * 16).toString(16))
        .join('');
    callback(null, `${name}-${randomName}${fileExtName}`);
};

And finally, I have a different route to import or parse data, and then I could save it into my database.

// You have to define entity that is as 2nd argument of csvParsing and also a mendatory.
class Coin {
  unix: number
  date: string
  symbol: string
  open: number
  close: number
  high: number
  low: number
  "Volume BTC": number
  "Volume USDT": number
  tradecount: number
}


// An import end route
@Get('import')
  async import(){
    const csvPath = getCSVFile();
    console.log(" => ", csvPath);
    const stream = fs.createReadStream(csvPath)
    const entities: Coin[] = await this.csvParser.parse(stream, Coin)
    // You will get JSON
    console.log(entities);
  }

You can do it in the same controller action /upload. Although, in my scenario, I have to do it through a different API call.

Upvotes: 5

Related Questions