-2

I am trying to upload a csv file through react at frontend & node.js server and store it in an array. I have used fast csv module to parse this csv file but fast csv module is asking for a buffer or url . My react is sending me an blank object. I am badly stuck , please help me out of it. I am counting on you .

import React from 'react';
import axios from 'axios';

const [company, setCompany] = React.useState('');
const [city, setcity] = React.useState("");
const [file, setFile] = React.useState("");
const [open, setOpen] = React.useState(false);

let csvData = new FormData();
csvData.append("file", file);


const handleSubmit = async () => {
    try {
        const res = await axios.post('http://localhost:5000/csv',  { csvData } );
        console.log(res);
    } catch (error) {
        console.error(error);
    }
};

 <input className={classes.input} id="contained-button-file" multiple type="file" 
         onChange={(e) => setFile(e.target.files[0])} />

                    <label htmlFor="contained-button-file">

                        <Button variant="contained" color="primary"
                        component="span" startIcon={<CloudUpload />}>
                            Upload Data
                        </Button>

                    </label>

UPDATE:

updated backend code from responses provided so that I can get help on front end code now.

After updating code get error from backend.

error:TypeError: Cannot read property 'path' of undefined

My backend code goes in this way:

import fs from 'fs';
import multer from 'multer';
const upload = multer({ dest: '/tmp/csv/' });
const csv = require('fast-csv');

router.post('/csv', upload.single('file'), (req, res, next) => {
let filerows = [];

let stream = fs.createReadStream(req.file.path);

stream.pipe(
    // csv.fromPath(req.file.path)
    csv
        .parse()
        .on('data', (data) => {
            filerows.push(data);
        })
        .on('error', () => {
            res.status(500).json({ message: 'Failed to upload' });
        })
        .on('end', () => {
            // console.log(filerows);
            
            const sql =
            'INSERT INTO bikes_database(website, company_name, category,city, brand_name, bike_name, bike_url, hour_rent, weekday_rent, weekend_rent, 7_days_rent, 15_days_rent, 30_days_rent, gst, convinence_fee,booking_confirmation, helmet,deposit, km_limit, speed_limit, home_delivery, product_page) VALUES ?';
            
            db.query(sql, [filerows], (err, result) => {
                if (err) throw err;
                res.json("uploaded successfully")
            });

            fs.unlinkSync(req.file.path);
        })
);

});

Kunal Kumar
  • 39
  • 12
  • Please put text in your post, _as text_. Don't use screenshots. Remember to read through [how to ask a good question](/help/how-to-ask) and update your post accordingly. – Mike 'Pomax' Kamermans Sep 05 '20 at 03:45
  • Please see [this meta post](https://meta.stackoverflow.com/a/285557/272109) which explains why it's important to post code, errors, etc. as formatted text instead of images. – David Makogon Sep 05 '20 at 03:49

2 Answers2

0

You are missing the multer middleware to provide path location for the file. Without it path may be undefined which is probs what's causing your error

  const fs = require('fs');
  const multer = require('multer');
  const upload = multer({ dest: 'tmp/csv/' });
  const csv = require('fast-csv');

  router.post('/csv', upload.single('file'), function (req, res) {
    const fileRows = [];

    // open uploaded file
    csv.fromPath(req.file.path)
      .on("data", function (data) {
        fileRows.push(data); // push each row
      })
      .on("error", function () {
          res.status(500).json({
              message: "Failed to upload file"
          });
      })
      .on("end", function () {
        console.log(fileRows)
        fs.unlinkSync(req.file.path);   // remove temp file
        
        //process "fileRows" and respond
        
         res.json({
            message: "Upload Completed!"
         });
      })
  }));

As for your react code, I can see that you’re setting any elements with the text returned from request. Inside handle submit you will need to set the text from the response received. Something like this but you also need to handle setting the error message if that’s received instead

     this.setState({
         text: response.data.message 
     });
Edward Romero
  • 2,905
  • 1
  • 5
  • 17
0

for backend my updated code works fine:

import fs from 'fs';
import multer from 'multer';
const upload = multer({ dest: '/tmp/csv/' });
const csv = require('fast-csv');

router.post('/csv', upload.single('file'), (req, res, next) => {
let filerows = [];

let stream = fs.createReadStream(req.file.path);

stream.pipe(
// csv.fromPath(req.file.path)
csv
    .parse()
    .on('data', (data) => {
        filerows.push(data);
    })
    .on('error', () => {
        res.status(500).json({ message: 'Failed to upload' });
    })
    .on('end', () => {
        // console.log(filerows);
        
        const sql =
        'INSERT INTO bikes_database(website, company_name, category,city, brand_name, 
   bike_name, bike_url, hour_rent, weekday_rent, weekend_rent, 7_days_rent, 
   15_days_rent, 30_days_rent, gst, convinence_fee,booking_confirmation, 
   helmet,deposit, km_limit, speed_limit, home_delivery, product_page) VALUES ?';
        
        db.query(sql, [filerows], (err, result) => {
            if (err) throw err;
            res.json("uploaded successfully")
        });

        fs.unlinkSync(req.file.path);
    })
  );

For Frontend we have:

 import React from 'react';
 import axios from 'axios';

const [company, setCompany] = React.useState('');
const [city, setcity] = React.useState("");
const [file, setFile] = React.useState("");
const [open, setOpen] = React.useState(false);

let csvData = new FormData();
csvData.append("file", file);


const handleSubmit = async () => {
try {
    const res = await axios({
            method: 'post',
            url: 'http://localhost:5000/csv',
            data: csvData,
            headers: { 'Content-Type': 'multipart/form-data' },
        });
    console.log(res);
} 
catch (error) {
    console.error(error);
}
 };

 <input className={classes.input} id="contained-button-file" multiple type="file" 
     onChange={(e) => setFile(e.target.files[0])} />

                <label htmlFor="contained-button-file">

                    <Button variant="contained" color="primary"
                    component="span" startIcon={<CloudUpload />}>
                        Upload Data
                    </Button>

                </label>
Kunal Kumar
  • 39
  • 12