Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

request body is empty on post request when using FormData()

I am trying to send formdata from react to express server. When sending json payload, i get what is expected. However, when sending data using formdata.append, i get empty req body.

I tried various solutions posted here for similar problem but nothing seemed to work for me.

Hope someone can help

app.js

require('./database/db')
const express = require('express')
const cors = require('cors')
const userRouter = require('./routes/user')
const menuRouter = require('./routes/menu')

const app = express()

app.use(express.json())
app.use(express.urlencoded({ extended: true }))
app.use(cors())

app.use(express.static('public'))

app.use(userRouter)
app.use(menuRouter)

app.listen(9000, () => console.log('Server started at port: 9000'))

route i want to call

router.post(
    '/addMenu',
    [
        check('name', 'Menu name is required!').not().isEmpty(),
        check('price', 'Price is required!').not().isEmpty(),
        check('category', 'Category is required!').not().isEmpty(),
    ],
    verifyAuth,
    (req, res) => {
        console.log(req.body)
// body is empty here
})

react bootstrap form

import { Component } from 'react'
import axios from '../axios'
import { Link } from 'react-router-dom'
import { Button, Form, Card } from 'react-bootstrap'

export default class AddMenu extends Component {
    constructor(props) {
        super(props)
        this.state = {
            name: '',
            price: '',
            category: '',
            image: '',
        }

        this.inputHandler = this.inputHandler.bind(this)
        this.inputHandler = this.inputHandler.bind(this)
        this.addMenu = this.addMenu.bind(this)
    }

    inputHandler = (e) => {
        this.setState({
            [e.target.name]: e.target.value,
        })
    }
    fileHandler = (e) => {
        this.setState({
            image: e.currentTarget.files[0],
        })
    }
    addMenu = (e) => {
        e.preventDefault()
        const { name, price, category, image } = this.state

        const data = new FormData()

        data.append('name', name)
        data.append('price', price)
        data.append('category', category)
        data.append('file', image)

        axios
            .post('/addMenu', data)
            .then((response) => {
                if (response.data.success) {
                    alert(response.data.menu)
                } else {
                    alert('something went wrong')
                }
            })
            .catch()
    }

    render() {
        return (
            <div className='col-lg-12 col-centered' style={{ height: '44rem' }}>
                <Card
                    style={{
                        width: '20rem',
                        marginLeft: '420px',
                        marginTop: '80px',
                        float: 'left',
                        height: '34rem',
                    }}
                >
                    <Card.Img
                        variant='top'
                        src='https://image.freepik.com/free-vector/food-delivery-service-fast-food-delivery-scooter-delivery-service-illustration_67394-869.jpg'
                    />
                    <Card.Body>
                        <Card.Title>Add Menu</Card.Title>
                        <Card.Text>
                            Although a great restaurant experience must include great food, a bad restaurant experience can be achieved through bad service alone.
                            Ideally, service is invisible.
                        </Card.Text>
                        <Button as={Link} to='/' variant='info'>
                            Go to Home
                        </Button>
                    </Card.Body>
                </Card>
                <Card
                    style={{
                        width: '22rem',
                        marginTop: '78px',
                        float: 'left',
                        height: '34rem',
                    }}
                >
                    <Form className='add-menu' onSubmit={this.addMenu}>
                        <h2>Add Menu</h2>
                        <Form.Group controlId='formBasicName'>
                            <Form.Label>Restaurant Name</Form.Label>
                            <Form.Control
                                type='text'
                                name='name'
                                placeholder='Enter Restaurant Name'
                                value={this.state.name}
                                onChange={(event) => this.inputHandler(event)}
                            />
                        </Form.Group>

                        <Form.Group controlId='formBasicPrice'>
                            <Form.Label>Enter Price</Form.Label>
                            <Form.Control type='text' name='price' placeholder='Price' value={this.state.price} onChange={(event) => this.inputHandler(event)} />
                        </Form.Group>

                        <Form.Group controlId='formBasicCategory'>
                            <Form.Label>Enter Category</Form.Label>
                            <Form.Control
                                name='category'
                                type='text'
                                placeholder='Enter Menu Category'
                                value={this.state.category}
                                onChange={(event) => this.inputHandler(event)}
                            />
                        </Form.Group>

                        <Form.Group controlId='formBasicImage'>
                            <Form.Label>Enter Category</Form.Label>
                            <Form.Control name='image' type='file' onChange={this.fileHandler} />
                        </Form.Group>

                        <Button className='btn-lg btn-block' variant='info' type='submit'>
                            Add Menu
                        </Button>
                    </Form>
                </Card>
                <br />
                <br />
                <br />
            </div>
        )
    }
}

routes/menu implementation

const router = require('express').Router()
const { verifyAuth } = require('../middleware/auth')
const upload = require('../middleware/fileUpload')
const Menu = require('../models/Menu')
const { check, validationResult } = require('express-validator')

// add a menu item
router.post(
    '/addMenu',
    [
        check('name', 'Menu name is required!').not().isEmpty(),
        check('price', 'Price is required!').not().isEmpty(),
        check('category', 'Category is required!').not().isEmpty(),
    ],
    verifyAuth,
    (req, res) => {
        console.log(req.body)
        if (req.authUser.userType === 'Restaurant') {
            const validationErr = validationResult(req)
            if (validationErr.isEmpty()) {
                let image = null
                const { name, price, category } = req.body
                if (req.file) {
                    upload(req, res, (err) => {
                        if (err) {
                            response.status(500).json({ success: false, message: err })
                        } else {
                            image = req.file.filename
                        }
                    })
                }
                const newMenu = new Menu({ name, price, category, addedBy: req.authUser._id, image })
                newMenu
                    .save()
                    .then((menu) => res.status(201).json({ success: true, message: 'Menu added', menu }))
                    .catch((error) => res.status(500).json({ success: false, message: error.message }))
            } else {
                res.status(400).json({ success: false, errors: validationErr.array() })
            }
        } else {
            res.status(403).json({ success: true, message: 'Insufficient privileges' })
        }
    }
)

// get all menu items
router.get('/menus', (req, res) => {
    Menu.find()
        .populate('addedBy', '-_id name')
        .then((menus) => res.status(200).json({ success: true, menus }))
        .catch((error) => res.status(500).json({ success: false, message: error.message }))
})

module.exports = router

Even in Postman x-www-form-urlencoded sends the data but form-data does not

like image 798
Raj Avatar asked Dec 29 '25 08:12

Raj


2 Answers

Form data will get empty object if there is no file given to it via routes like this.

import multer from 'multer';
    router.post(
    '/addMenu',
    multer().single("keyNameForFile"),
    [
        check('name', 'Menu name is required!').not().isEmpty(),
        check('price', 'Price is required!').not().isEmpty(),
        check('category', 'Category is required!').not().isEmpty(),
    ],
    verifyAuth,
    (req, res) => {
        console.log(req.body)
// body is empty here
})

Don't know what cause this behaviour but use form-data when you are sending some file like image doc etc.

like image 115
Syed Mohib Uddin Avatar answered Jan 01 '26 03:01

Syed Mohib Uddin


You should set the Content-Type of your request header as Content-Type: application/x-www-form-urlencoded this will allow express to access you form data in the body

To set the header in axios you can perform it like this

const config = {
    headers: {
        'Content-Type': 'application/x-www-form-urlencoded'
    }
};

and you perform a request to you backend with the header set like this

axios.post('/addMenu', data, config)
    .then({ /*...*/});
like image 21
Yves Kipondo Avatar answered Jan 01 '26 02:01

Yves Kipondo



Donate For Us

If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!