I am trying to add multiple images in a form with some other data when i click on "post ad" button which is a button to trigger a function which will append our data to FormData() everything is appending perfectly but when it comes to appending image it is only appending one image and ultimately store one image in database.Screenshot of what i m getting from "req.body"and "req.files" is given below. can anybody sort out this issue
Frontend code
import React, { useState } from 'react';
import './Popup.css';
import axios from 'axios';
import { Button } from './Button';
import {useHistory} from 'react-router-dom';
function PostAd() {
const history = useHistory();
const [newAd, setNewAd] = useState(
{
registeration: '',
intcolor: '',
extcolor: '',
mileage: '',
price: '',
make: '',
model:'',
year: '',
discription: '',
mobilenumber: '',
secondmobilenumber: '',
address: '',
images:'',
});
const handleChange = (e) => {
setNewAd({...newAd, [e.target.name]: e.target.value});
}
const handlePhoto = (e) => {
setNewAd({...newAd, images: e.target.files});
}
const handleSubmit = (e) => {
e.preventDefault();
let url = 'http://localhost:3000/addata'
const formDataa = new FormData();
formDataa.append('registeration', newAd.registeration);
formDataa.append('intcolor', newAd.intcolor);
formDataa.append('extcolor', newAd.extcolor);
formDataa.append('price', newAd.price);
formDataa.append('mileage', newAd.mileage);
formDataa.append('make', newAd.make);
formDataa.append('model', newAd.model);
formDataa.append('year', newAd.year);
formDataa.append('discription', newAd.discription);
formDataa.append('mobilenumber', newAd.mobilenumber);
formDataa.append('secondmobilenumber', newAd.secondmobilenumber);
formDataa.append('address', newAd.address);
for (const key of Object.keys(newAd.images)) {
formDataa.append('images',newAd.images[key])
}
console.log(formDataa)
axios.post(url ,formDataa,{
headers:{'Content-Type':'multipart/form-data'}
})
.then(res => {
console.log(res);
history.push('/slider')
})
.catch(err => {
console.log(err);
});
}
return(
<form method="POST" onSubmit={handleSubmit} encType='multipart/form-data' >
<div style={{display:'block'}} class='container-fluid' >
<div style={{backgroundColor:'#1c2237',marginTop:'40px'}} class='row'>
<div class='col-lg-12'>
<p style={{textAlign:'center',marginTop:'20px',fontSize:'1.5rem',fontWeight:'bold',color:'#f00946'}}>Sell your car in three easy steps</p>
<p style={{textAlign:'center',fontSize:'18px',marginTop:'-15px',fontFamily:'-moz-initial'}}>It's free and don't take much of your time</p>
</div>
</div>
<div style={{backgroundColor:'#1c2237',marginBottom:'30px'}} class='row'>
<div class='col-lg-2 col-md-2 col-sm-0' ></div>
<div class='col-lg-8 col-md-8 col-sm-12' >
<div class='row'>
<div class='col-lg-4 col-md-4 col-sm-12 ' style={{height:'60px'}}>
<img className='postimg' alt=" Enter Your Car Information" src="https://wsa1.pakwheels.com/assets/sell-icons/car-221614dec8c0f3717dede556a5daad01.svg"/>
<p style={{display:'inline',fontWeight:'bold',fontSize:'15px'}}>Enter Car Information</p>
</div>
<div class='col-lg-4 col-md-4 col-sm-12' style={{height:'60px'}}>
<img className='postimg' alt=" Upload Photos" src="https://wsa1.pakwheels.com/assets/sell-icons/photos-708994063564767acaca738e1261f90d.svg"/>
<p style={{display:'inline',fontWeight:'bold',fontSize:'15px'}}>Upload Images</p>
</div>
<div class='col-lg-4 col-md-4 col-sm-12' style={{height:'60px'}}>
<img className='postimg' alt=" Enter Your Selling Price" src="https://wsa4.pakwheels.com/assets/sell-icons/tag-3ba531fca999b37f89be28609fe9e9c0.svg"/>
<p style={{display:'inline',fontWeight:'bold',fontSize:'15px'}}>Enter Your Demand</p>
</div>
</div>
</div>
<div class='col-lg-2 col-md-2 col-sm-0' ></div>
</div>
<div style={{overflow:'auto'}} class='row'>
<div class='col-lg-1 col-md-1 col-sm-0'></div>
<div style={{backgroundColor:'#1c2237'}} class='col-lg-10 col-md-10 col-sm-10'>
<h3 className='mainh' style={{textAlign:'center'}}>Car Information</h3>
<div class='row'>
<div class='col-lg-6'>
<div className="form-group">
<label className='lab'>City:</label>
<input type="text" name="address" id="address" className="form-control" placeholder="Please enter your city" autoComplete="off"
value={newAd.address}
onChange={handleChange}
/>
</div>
</div>
<div class='col-lg-6'>
<div className="form-group">
<label className='lab' >Registeration City:</label>
<input type="text" name="registeration" id="registeration" className="form-control" placeholder=" Please enter car registeration city" autoComplete="off"
value={newAd.registeration}
onChange={handleChange}/>
</div>
</div>
</div>
<div class='row'>
<div class='col-lg-6'>
<div className="form-group">
<label className='lab'>Interior Color:</label>
<input type="text" name="intcolor" id="intcolor" className="form-control" placeholder="Interior Color" autoComplete="off"
value={newAd.intcolor}
onChange={handleChange}
/>
</div>
</div>
<div class='col-lg-6'>
<div className="form-group">
<label className='lab' >Exterior Color:</label>
<input type="text" name="extcolor" id="extcolor" className="form-control" placeholder="Exterior color" autoComplete="off"
value={newAd.extcolor}
onChange={handleChange}
/>
</div>
</div>
</div>
<div class='row'>
<div class='col-lg-6 col-md-6 col-sm-12'>
<div className="form-group">
<label className='lab' >Mileage:</label>
<input type="number" name="mileage" id="mileage" className="form-control" placeholder="Please enter your car current km's driven" autoComplete="off"
value={newAd.mileage}
onChange={handleChange}
/>
</div>
</div>
<div class='col-lg-6 col-md-6 col-sm-12'>
<div className="form-group">
<label className='lab' >Price:</label>
<input type="number" name="price" id="price" className="form-control" placeholder="Please enter your asking price " autoComplete="off"
value={newAd.price}
onChange={handleChange}
/>
</div>
</div>
</div>
<div class='row'>
<div class='col-lg-4 col-md-4 col-sm-12'>
<div className="form-group">
<label className='lab' >Make:</label>
<input type="text" name="make" id="make" className="form-control" placeholder="Toyota/Honda/KIA etc." autoComplete="off"
value={newAd.make}
onChange={handleChange}
/>
</div>
</div>
<div class='col-lg-4 col-md-4 col-sm-12'>
<div className="form-group">
<label className='lab' >Model:</label>
<input type="text" name="model" id="model" className="form-control" placeholder="Corolla/City/Sportage etc." autoComplete="off"
value={newAd.model}
onChange={handleChange}
/>
</div>
</div>
<div class='col-lg-4 col-md-4 col-sm-12 '>
<div className="form-group">
<label className='lab' >Year:</label>
<input type="number" name="year" id="year" className="form-control" placeholder="Year of Make" autoComplete="off"
value={newAd.year}
onChange={handleChange}
/>
</div>
</div>
</div>
<div class='row'>
<div class='col-lg-12 col-md-12 col-sm-12'>
<div className="form-group">
<label className='lab' >Ad Description</label>
<input type="text" name="discription" id="discription" className="form-control" placeholder="Describe your vehicle" autoComplete="off"
value={newAd.discription}
onChange={handleChange}
/>
</div>
</div>
</div>
</div>
</div>
<div class='col-lg-1 col-md-1 col-sm-0'></div>
<div style={{overflow:'auto'}} class='row'>
<div class='col-lg-1 col-md-1 col-sm-0'></div>
<div style={{backgroundColor:'#1c2237',marginTop:'30px',display:'block'}} class='col-lg-10 col-md-10 col-sm-10'>
<h3 className='mainh' style={{textAlign:'center',backgroundColor:'#1c2237'}}>Upload Car Pictures</h3>
<div style={{justifyContent:'center',borderWidth:'2px',borderColor:'red',borderRadius:'5px',borderStyle:'dotted'}} class='row'>
<div class='col-lg-12'>
<img className='centimg' alt="Photos" src="https://wsa4.pakwheels.com/assets/photos-d7a9ea70286f977064170de1eeb6dca8.svg" />
<input
className='mulinp'
type='file'
name='images'
onChange={handlePhoto}
multiple
/>
</div>
<div class='row'>
<div class='col-lg-6'>
<i style={{marginTop:'30px',marginBottom:'20px'}} class="fa fa-check-circle-o"><strong>Add atleast 8 images for better sale results</strong></i>
</div>
<div class='col-lg-6'>
<i style={{marginTop:'30px',marginBottom:'20px'}} class="fa fa-check-circle-o"><strong>Adding clear Front, Back and Interior </strong>will also boast your sale chances</i>
</div>
</div>
</div>
</div>
</div>
<div class='col-lg-1 col-md-1 col-sm-0'></div>
<div style={{overflow:'auto'}} class='row'>
<div class='col-lg-1 col-md-1 col-sm-0'></div>
<div style={{backgroundColor:'#1c2237',marginTop:'30px',display:'block'}} class='col-lg-10 col-md-10 col-sm-10'>
<h3 className='mainh' style={{textAlign:'center',backgroundColor:'#1c2237'}}>Contact Information</h3>
<div style={{justifyContent:'center'}} class='row'>
<div class='col-lg-6'>
<div className="form-group">
<h5 className='lab'>Mobile Number:</h5>
<input style={{width:'250px',display:'inline',marginLeft:'8px'}} type="number" name="mobilenumber" id="mobilenumber" className="form-control" placeholder="Enter phone number" autoComplete="off"
value={newAd.mobilenumber}
onChange={handleChange}
/>
</div>
<div style={{marginTop:'10px'}} className="form-group">
<h5 className='lab'>Secondary(OPT):</h5>
<input style={{width:'250px',display:'inline',marginLeft:'8px'}} type="number" name="secondmobilenumber" id="secondmobilenumber" className="form-control" placeholder="Enter phone number" autoComplete="off"
value={newAd.secondmobilenumber}
onChange={handleChange}
/>
</div>
</div>
<div class='col-lg-6'>
<p style={{fontSize:'15px',alignItems:'center',justifyContent:'center',textAlign:'center',marginTop:"15px",borderWidth:'2px',borderColor:'red',borderRadius:'5px',borderStyle:'dotted'}}>Enter a genuine 11 digit mobile no. with format 03XXXXXXXXX. All inquires will come on this number</p>
</div>
</div>
<div style={{justifyContent:'center',alignItems:'center',marginTop:'50px'}} class='row'>
<button type="submit" name="postad" id="postad" className="btn btn-primary btn-block">Post Ad</button>
</div>
</div>
</div>
<div class='col-lg-1 col-md-1 col-sm-0'>
</div>
</div>
</form>
)}
export default PostAd;
Backend Code
const multer = require('multer');
const Ads = require("../model/adsSchema");
require("../db/conn");
let path = require('path');
const storage = multer.diskStorage({
destination: function(req, file, cb) {
cb(null, './uploads/profilepics');
},
filename: function(req, file, cb) {
cb(null, Date.now() path.extname(file.originalname));
}
});
const fileFilter = (req, file, cb) => {
const allowedFileTypes = ['image/jpeg', 'image/jpg', 'image/png'];
if(allowedFileTypes.includes(file.mimetype)) {
cb(null, true);
} else {
cb(null, false);
}
}
let upload = multer({ storage: storage, fileFilter: fileFilter });
router.route('/addata').post(upload.array('images',15),async(req, res) => {
console.log(req.body)
console.log(req.body.address)
console.log(req.body.year)
console.log(req.files.length)
const images = [];
const registeration = req.body.registeration;
const intcolor = req.body.intcolor;
const extcolor = req.body.extcolor;
const mileage = req.body.mileage;
const price = req.body.price;
const make = req.body.make;
const model = req.body.model;
const year = req.body.year;
const discription = req.body.discription;
const mobilenumber = req.body.mobilenumber;
const secondmobilenumber = req.body.secondmobilenumber;
const address = req.body.address;
for (var i = 0; i < req.files.length; i ) {
images.push(req.files[i].filename)
}
console.log(images)
const newAdData = {
registeration,
intcolor,
extcolor,
mileage,
price,
make,
model,
year,
discription,
mobilenumber,
secondmobilenumber,
address,
images,
}
console.log(newAdData)
try{
const adsave = await Ads.create(newAdData)
return res.status(201).json({
success: true,
data: adsave
});
}
catch(err){
console.error(err);
res.status(500).json({ error: 'Server error' });
}
});
Database Schema
const mongoose = require('mongoose');
const geocoder = require('../utils/geocoder')
const adsSchema = new mongoose.Schema({
registeration: {
type: String,
required: true,
},
intcolor:{
type: String,
required: true
},
extcolor:{
type: String,
required: true
},
mileage:{
type: Number,
required: true
},
price:{
type: Number,
required: true
},
make:{
type: String,
required: true
},
model:{
type: String,
required: true
},
year:{
type: Number,
required: true
},
discription:{
type: String,
required: true
},
mobilenumber:{
type: Number,
required: true
},
secondmobilenumber:{
type: Number
},
address: {
type: String,
required: true
},
images:{
type: Array,
required:true
},
location: {
type: {
type: String,
enum: ['Point']
},
coordinates: {
type: [Number],
index: '2dsphere'
},
formattedAddress:{
type: String
}
},
createdAt: {
type: Date,
default: Date.now
}
});
adsSchema.pre('save', async function(next) {
const loc = await geocoder.geocode(this.address);
this.location ={
type:'point',
coordinates : [loc[0].longitude,loc[0].latitude],
formattedAddress: loc[0].formattedAddress
}
this.address = undefined;
next();
});
module.exports = mongoose.model('ads', adsSchema);
CodePudding user response:
this lines
const handlePhoto = (e) => {
setNewAd({...newAd, images: e.target.files});
}
when you want to add new image to your state, you ignore old images when use
images: e.target.files
you need to change this line
const handlePhoto = (e) => {
setNewAd({...newAd, images: [...newAd.images, ...e.target.files]});
}