When I test sending a request containing both image and text grabbbed from user, it comes through to the backend with proper data when I use Postman. Not from React front-end, though. Request does come through but req.body seems to be empty when I console.log it from backend. What am I doing wrong? I am using Multer.
//FRONT-END
import React, { useState } from 'react';
import axios from 'axios';
const ListProperty = (props) => {
const [address, setAddress] = useState('');
const [file, setFile] = useState(null);
const [filename, setFilename] = useState('Choose File');
const handleAddressChange = (evt) => {
setAddress(evt.target.value);
};
const handlePhotoSelect = (evt) => {
setFile(evt.target.files[0]);
setFilename(evt.target.files[0].name);
};
const handleSubmit = async (evt) => {
evt.preventDefault();
const formData = new FormData();
formData.append('address', address);
formData.append('upload', file);
console.log(formData);
try {
axios.post('http://localhost:3000/listproperty', {
headers: { 'Content-Type': 'multipart/form-data' },
body: formData,
});
} catch (err) {
console.log(err);
}
};
return (
<div>
<h2>Property Listing Form</h2>
<span>Provide property address and Photo</span>
<form onSubmit={handleSubmit}>
<input
type="text"
value={address}
onChange={handleAddressChange}
name={address}
placeholder="Enter address"
/>
<br />
<input type="file" onChange={handlePhotoSelect} />
<button>Click to list</button>
</form>
</div>
);
};
export default ListProperty;
//BACK-END
const express = require('express');
const PropertyModel = require('../models/propertyModel');
const router = new express.Router();
const UserModel = require('../models/userModel');
const multer = require('multer');
const storage = multer.diskStorage({
destination: function (req, file, cb) {
cb(null, 'public/images');
},
filename: function (req, file, cb) {
const uniqueName = `${Math.random().toString(32).slice(2)}.jpg`;
req.image = uniqueName;
cb(null, uniqueName);
},
});
const upload = multer({ storage });
router.post(
'/listproperty',
upload.single('upload'),
async (req, res) => {
console.log('hitting Backend router');
const property = new PropertyModel({
...req.body,
owner: req.user._id,
photo: req.image,
});
await UserModel.findByIdAndUpdate(req.user._id, {
$push: { properties: property._id },
});
try {
await property.save();
res.status(200).send(property);
} catch (err) {
console.log(err);
res.status(400).send(err);
}
}
);
module.exports = router;
your axios request is not right. axios post request accepts data as a second argument and third argument is for options ( headers etc ),
axios.post('http://localhost:3000/listproperty', formData, {
headers: {
'Content-Type': 'multipart/form-data'
}
});
another thing is your request is not being triggered at all. try setting input type to submit instead of using the button to trigger onSubmit handler of the form.
<form onSubmit={handleSubmit}>
<input
type="text"
value={address}
onChange={handleAddressChange}
name={address}
placeholder="Enter address"
/>
<br />
<input type="file" onChange={handlePhotoSelect} />
<input type="submit" value="Submit" />
</form>
If you are sending form data in the body you need to use the formidable npm module
you can install it using npm i formidable
then require formidable at top of the file
var formidable = require("formidable");
router.post(
'/listproperty',
upload.single('upload'),
async (req, res) => {
var form = new formidable.IncomingForm();
form.multiples = false;
form.parse(req, async function (err, fields, files) {
/**now here you can get all files in files and fields with fields
in your case you have sent
formData.append('address', address);
formData.append('upload', file);
above two data in form
so you can get your image from files.upload
and address fields.address **/
})
})
In addition, I would suggest you use Axios for api calls
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.