Search code examples
javascriptnode.jsreactjsexpressmulter

Multer re.file Returns Undefined


I am in need of some assistance. I am using react on the front end and node js on the back end with MySQL as the database. In node js, I am using multer to file transfer, but multer returns undefined for the file. I am not sure if it is because I am trying to transfer extra information within the Axios post section. My code is attached, any help will be greatly appreciated.

React Js file:

import React, { useEffect, useState } from 'react';
import './Properties_Upload.css';
import Navbar from '../../../Components/Navbar/Navbar';
import Footer from '../../../Components/Footer/Footer';
import Axios from 'axios';
import { useNavigate } from 'react-router-dom';

export default function Properties_Upload() {
    const [addressLine, setAddressLine] = useState('');
    const [addressLine2, setAddressLine2] = useState('');
    const [addressCity, setAddressCity] = useState('');
    const [addressState, setAddressState] = useState('');
    const [addressZipCode, setAddressZipCode] = useState('');
    const [mlsID, setMLSID] = useState('');
    const [selectedFile, setSelectedFile] = useState('');
    const [errorMessage, setErrorMessage] = useState('');
    const navigate = useNavigate();
    
    const propertyInfoHandler = async () => {
        const data = new FormData() 

        for (var x = 0; x < selectedFile.length; x++) {
            data.append('file', selectedFile[x]);
        }

        Axios.post('http://localhost:3001/property/properties_upload', data, {
            addressLine: addressLine,
            addressLine2: addressLine2,
            addressCity: addressCity,
            addressState: addressState,
            addressZipCode: addressZipCode,
            mlsID: mlsID
        })
        .then((response) => {
            navigate('/properties');
            if (response.data.errorMessage){
                setErrorMessage(response.data.message);
            }
        });
    };

    return (
        <>
            <Navbar />
            <div className='propertiesUploadBody'>
                <h1>Properties Upload</h1>
                <div className='propertyInfoFormBody'>
                    <h1>Property Information</h1>
                    <p className='addressLine'> *Property address: <input name='addressLine' placeholder='Address' required autoComplete="off" onChange={(e) => setAddressLine(e.target.value)} /> </p>
                    <p className='addressLine2'> Apartment/Suite/Unit: <input name='addressLine2' placeholder='Apartment/Suite/Unit' autoComplete="off" onChange={(e) => setAddressLine2(e.target.value)} /> </p>
                    <p className='addressCity'> *Property city: <input name='addressCity' placeholder='City' required autoComplete="off" onChange={(e) => setAddressCity(e.target.value)} /> </p>
                    <p className='addressState'> *Property state: <input name='addressState' placeholder='State' maxLength={2} required autoComplete="off" onChange={(e) => setAddressState(e.target.value)} /> </p>
                    <p className='addressZipCode'> *Property zip code: <input type='number' name='addressZipCode' placeholder='Zip Code' required autoComplete="off" onChange={(e) => setAddressZipCode(e.target.value)} /> </p>
                    <p className='propertyMLSID'> MLS ID: <input type='number' name='propertyMLSID' placeholder='MLS ID' required autoComplete="off" onChange={(e) => setMLSID(e.target.value)} /></p>
                </div>
                <div className='propertyFileFormBody'>
                    <h1>Property Image Upload</h1>
                    <p> Upload Images of the property.</p>
                    <input className='uploadFiles' type='file' name='file' multiple required onChange={(e) => setSelectedFile(e.target.files)} />
                </div>
                <h2 style={{color: "red"}}>{errorMessage}</h2>
                <button className='uploadButton' onClick={propertyInfoHandler}>Upload Property</button>
            </div>
            <Footer />
        </>
    )
}

Node Js File:

const express = require('express');
const router = express.Router();
const db = require('../config/db');
const bcrypt = require('bcrypt');
const saltRounds = 10;
const session = require('express-session');
const bodyParser = require('body-parser');
const app = express();
const SqlDbStore = require('express-mysql-session')(session);
const passport = require('passport');
const cookieParser = require('cookie-parser');
const multer = require('multer');
//----------------------------------------- BEGINNING OF PASSPORT MIDDLEWARE AND SETUP ---------------------------------------------------
app.use(cookieParser());
app.use(bodyParser.json());
app.use(bodyParser.urlencoded({ extended: true }));
app.use(passport.session());
app.use(session({
    key: 'session_cookie_name',
    secret: 'session_cookie_secret',
    store: new SqlDbStore({
    host: 'localhost',
    port: 3306,
    user: 'root',
    password: '**************',
    database: '**************',
    }),
    resave: false,
    saveUninitialized: false,
    cookie:{
        maxAge:1000*60*60*24,
        secure: false
    }
}));
const storage = multer.diskStorage({
  destination: function (req, file, cb) {
    cb(null, './Images');
  },
  filename: function (req, file, cb) {
    cb(null, Date.now() + '-' + file.originalname );
  }
});

const upload = multer({ storage: storage }).array('file');
//----------------------------------------- END OF PASSPORT MIDDLEWARE AND SETUP ---------------------------------------------------
router.post('/properties_upload', (req, res) => {
  const address = req.body.addressLine;
  const address2 = req.body.addressLine2;
  const city = req.body.city;
  const state = req.body.state;
  const addressZipCode = req.body.addressZipCode;
  const mlsID = req.body.mlsID;
  const rentalID = Math.floor(Math.random()*90000) + 10000;
  // const imageFiles = req.body.data;

  upload(req, res, function (err) {
    if (err instanceof multer.MulterError) {
        return res.status(500).json(err)
    } else if (err) {
        return res.status(500).json(err)
    }
    console.log("fileInfo: " + req.file);
    return res.status(200).send(req.file)
  });
  
});

module.exports = router;

Solution

  • Properly Configured Setup

    React JS file:

    import React, { useEffect, useState } from 'react';
    import './Properties_Upload.css';
    import Navbar from '../../../Components/Navbar/Navbar';
    import Footer from '../../../Components/Footer/Footer';
    import Axios from 'axios';
    import { useNavigate } from 'react-router-dom';
    
    export default function Properties_Upload() {
        const [addressLine, setAddressLine] = useState('');
        const [addressLine2, setAddressLine2] = useState('');
        const [addressCity, setAddressCity] = useState('');
        const [addressState, setAddressState] = useState('');
        const [addressZipCode, setAddressZipCode] = useState('');
        const [mlsID, setMLSID] = useState('');
        const [selectedFile, setSelectedFile] = useState('');
        const [errorMessage, setErrorMessage] = useState('');
        const navigate = useNavigate();
        
        const propertyInfoHandler = () => {
            const url = 'http://localhost:3001/property/properties_upload';
            const data = new FormData() 
    
            for (var x = 0; x < selectedFile.length; x++) {
                data.append('files', selectedFile[x]);
            }
    
            Axios.post(url, data, {
                addressLine: addressLine,
                addressLine2: addressLine2,
                addressCity: addressCity,
                addressState: addressState,
                addressZipCode: addressZipCode,
                mlsID: mlsID
            })
            .then((response) => {
                navigate('/properties');
                if (response.data.errorMessage){
                    setErrorMessage(response.data.message);
                }
            });
        };
    
        return (
            <>
                <Navbar />
                <div className='propertiesUploadBody'>
                    <h1>Properties Upload</h1>
                    <div className='propertyInfoFormBody'>
                        <h1>Property Information</h1>
                        <p className='addressLine'> *Property address: <input name='addressLine' placeholder='Address' required autoComplete="off" onChange={(e) => setAddressLine(e.target.value)} /> </p>
                        <p className='addressLine2'> Apartment/Suite/Unit: <input name='addressLine2' placeholder='Apartment/Suite/Unit' autoComplete="off" onChange={(e) => setAddressLine2(e.target.value)} /> </p>
                        <p className='addressCity'> *Property city: <input name='addressCity' placeholder='City' required autoComplete="off" onChange={(e) => setAddressCity(e.target.value)} /> </p>
                        <p className='addressState'> *Property state: <input name='addressState' placeholder='State' maxLength={2} required autoComplete="off" onChange={(e) => setAddressState(e.target.value)} /> </p>
                        <p className='addressZipCode'> *Property zip code: <input type='number' name='addressZipCode' placeholder='Zip Code' required autoComplete="off" onChange={(e) => setAddressZipCode(e.target.value)} /> </p>
                        <p className='propertyMLSID'> MLS ID: <input type='number' name='propertyMLSID' placeholder='MLS ID' required autoComplete="off" onChange={(e) => setMLSID(e.target.value)} /></p>
                    </div>
                    <div className='propertyFileFormBody'>
                        <h1>Property Image Upload</h1>
                        <p> Upload Images of the property.</p>
                        <input className='uploadFiles' type='file' name='file' multiple required onChange={(e) => setSelectedFile(e.target.files)} />
                    </div>
                    <h2>{errorMessage}</h2>
                    <button className='uploadButton' onClick={propertyInfoHandler}>Upload Property</button>
                </div>
                <Footer />
            </>
        )
    }
    

    Node JS file:

    const express = require('express');
    const router = express.Router();
    const db = require('../config/db');
    const bcrypt = require('bcrypt');
    const saltRounds = 10;
    const session = require('express-session');
    const bodyParser = require('body-parser');
    const app = express();
    const SqlDbStore = require('express-mysql-session')(session);
    const passport = require('passport');
    const cookieParser = require('cookie-parser');
    const multer = require('multer');
    //----------------------------------------- BEGINNING OF PASSPORT MIDDLEWARE AND SETUP ---------------------------------------------------
    app.use(cookieParser());
    app.use(bodyParser.json());
    app.use(bodyParser.urlencoded({ extended: true }));
    app.use(passport.session());
    app.use(session({
        key: 'session_cookie_name',
        secret: 'session_cookie_secret',
        store: new SqlDbStore({
        host: 'localhost',
        port: 3306,
        user: 'root',
        password: '**************',
        database: '**************',
        }),
        resave: false,
        saveUninitialized: false,
        cookie:{
            maxAge:1000*60*60*24,
            secure: false
        }
    }));
    const multerDestination = './routes/Images/';
    const storage = multer.diskStorage({
      destination: function (req, files, cb) {
        cb(null, multerDestination);
      },
      filename: function (req, files, cb) {
        cb(null, Date.now() + '-' + files.originalname );
      }
    });
    const upload = multer({ storage: storage }).array('files');
    //----------------------------------------- END OF PASSPORT MIDDLEWARE AND SETUP ---------------------------------------------------
    router.post('/properties_upload', (req, res) => {
      const address = req.body.addressLine;
      const address2 = req.body.addressLine2;
      const city = req.body.city;
      const state = req.body.state;
      const addressZipCode = req.body.addressZipCode;
      const mlsID = req.body.mlsID;
      const rentalID = Math.floor(Math.random()*90000) + 10000;
    
      upload(req, res, function (err) {
        if (err instanceof multer.MulterError) {
            return res.status(500).json(err)
        } else if (err) {
            return res.status(500).json(err)
        }
        console.log("fileInfo: " + req.files);
        return res.status(200).send(req.files)
      });
    });
    
    module.exports = router;