Reputation: 442
I created one web service using node js. Using this service, I want to select user information and a photo from the react user interface and save them to mongodb. But The name of the photo is saved in Mongodb, but the photo is not saved under the directory ./public/uploads/.
What should I do to fix this error? Node js and react just started learning.
I share the codes I wrote below with you.
Model
const mongoose = require('mongoose');
const Schema = mongoose.Schema;
newSchema = new Schema({
name : String,
email : String,
password : String,
img: String
})
module.exports = mongoose.model('User', newSchema)
Routes
const express = require('express')
const User = require('../models/index')
const router = express.Router()
const multer = require('multer')
var imgStorage = multer.diskStorage({
destination: './public/uploads/',
filename:(req, file, cb)=>{
cb(null, file.fieldname+"_"+Date.now()+path.extname(file.originalname))
}
})
var upload = multer({
storage: imgStorage
}).single('file')
/* create new*/
router.post('/', upload, (req,res)=>{
user = new User({
name:req.body.name,
email:req.body.email,
password:req.body.password,
img: req.body.img
})
user.save(()=>{
res.json(user)
})
})
/* find all users */
router.get('/', (req, res) => {
User.find({},(err,data) =>{
res.json(data)
})
})
/* find user by id */
router.get('/:id',(req, res) =>{
User.findById(req.params.id, (err, data) =>{
res.json(data)
})
})
/* delete user by id */
router.delete('/:id',async (req, res) =>{
await User.findByIdAndDelete(req.params.id)
res.json({'message':'deleted'})
})
/* update */
router.put('/:id', async (req, res)=>{
await User.findByIdAndUpdate(req.params.is, req.body)
res.json({'message':'updated'})
})
module.exports = router
Index
const express = require('express');
const mongoose = require('mongoose');
const mongodb = require('mongodb');
const cors = require('cors');
mongoose.connect('mongodb://localhost:27017/admin?authSource=$[authSource] --username $[username]', {useNewUrlParser : true});
const app = express();
app.use(express.json())
app.use(cors())
app.use(express.urlencoded({extended:true}))
app.use('/api',require('./routes/index'))
const port = process.env.PORT || 8080
app.listen(port)
module.exports = new mongoose.model('User', newSchema)
React side
import React, {Component} from 'react';
import axios from 'axios';
class App extends React.Component {
constructor(props) {
super(props);
this.state = {
users: [],
id: 0,
name: '',
email: '',
password: '',
img: ''
}
}
componentDidMount() {
try {
axios.get('http://localhost:8080/api')
.then((res) => {
this.setState({
users: res.data,
id: 0,
name: '',
email: '',
password: '',
img: ''
})
})
} catch (e) {
console.log(e)
}
}
nameChange = event => {
this.setState({
name: event.target.value
})
}
emailChange = event => {
this.setState({
email: event.target.value
})
}
passwordChange = event => {
this.setState({
password: event.target.value
})
}
fileSelectedHandler = event =>{
this.setState({
img : event.target.files[0]
})
}
submit(event, id) {
event.preventDefault()
if (id === 0) {
// const fd = new FormData();
// fd.append('image', this.state.img, this.state.img.name);
axios.post('http://localhost:8080/api', {
name: this.state.name,
email: this.state.email,
password: this.state.password,
//img: this.state.img
img : this.state.img.name
}).then(()=>{
this.componentDidMount()
})
} else {
axios.put('http://localhost:8080/api/'+id, {
name: this.state.name,
email: this.state.email,
password: this.state.password,
img: this.state.img
}).then(()=>{
this.componentDidMount()
})
}
}
deleteUser(id) {
try {
axios.delete('http://localhost:8080/api/' + id)
.then((res) => {
this.componentDidMount()
})
console.log('Deleted successfully.')
} catch (e) {
console.log(e)
}
}
editUser(id) {
try {
axios.get('http://localhost:8080/api/' + id)
.then((res) => {
console.log(res.data)
this.setState({
id:res.data._id,
name: res.data.name,
email: res.data.email,
password: res.data.password
})
})
} catch (e) {
console.log(e)
}
}
render() {
return (
<div className="row">
<div className="col s6">
<form onSubmit={(e) => this.submit(e, this.state.id)}>
<div className="input-field col s12">
<i className="material-icons prefix">person</i>
<input value={this.state.name} onChange={(e) => this.nameChange(e)} type="text" id="autocomplete-input"
className="autocomplete" required/>
<label htmlFor="autocomplete-input">Name</label>
</div>
<div className="input-field col s12">
<i className="material-icons prefix">mail</i>
<input value={this.state.email} onChange={(e) => this.emailChange(e)} type="email" id="autocomplete-input"
className="autocomplete" required/>
<label htmlFor="autocomplete-input">Email</label>
</div>
<div className="input-field col s12">
<i className="material-icons prefix">vpn_key</i>
<input value={this.state.password} onChange={(e) => this.passwordChange(e)} type="password" id="autocomplete-input"
className="autocomplete" required/>
<label htmlFor="autocomplete-input">Password</label>
</div>
<div className="input-field col s12">
<input type="file" name="file" onChange={(e) => this.fileSelectedHandler(e)}/>
</div>
<br/>
<button className="btn waves-effect waves-light right blue" type="submit" name="action">Submit
<i className="material-icons right">send</i>
</button>
</form>
</div>
<div className="col s6">
<table>
<thead>
<tr>
<th>Name</th>
<th>Email</th>
<th>Password</th>
<th>IMG</th>
<th>Edit</th>
<th>Delete</th>
</tr>
</thead>
<tbody>
{this.state.users.map(user =>
<tr key={user._id}>
<td>{user.name}</td>
<td>{user.email}</td>
<td>{user.password}</td>
<td>
<img src="./public/uploads/user.img.name" width="80"/>
</td>
<td>
<button onClick={(e) => this.editUser(user._id)}
className="btn waves-effect waves-light green" type="submit" name="action">
<i className="material-icons right">edit</i>
</button>
</td>
<td>
<button onClick={(e) => this.deleteUser(user._id)}
className="btn waves-effect waves-light red" type="submit" name="action">
<i className="material-icons right">delete</i>
</button>
</td>
</tr>
)}
</tbody>
</table>
</div>
</div>
);
}
}
export default App;
Upvotes: 0
Views: 57
Reputation: 126
put this code in you route file and change name of below endpoint .hope it will works.Ask if you are not clear
var multer = require('multer');
var path = require('path')
var storage = multer.diskStorage({
destination: function (req, file, cb) {
cb(null, 'public/uploads')
},
filename: function (req, file, cb) {
cb(null, Date.now() + path.extname(file.originalname)) //Appending extension
}})
var upload = multer({ storage: storage });
router.post('/', upload.single('image'), (req,res)=>{
if (req.file.filename) {
req.body.image = req.file.filename;
}
user = new User({
name:req.body.name,
email:req.body.email,
password:req.body.password,
img: req.body.image
})
})
Upvotes: 0
Reputation: 126
You have to send file inside formData to the server like
inside submit function. Then send fd to server
const formData = new FormData();
formData.append('image', this.state.img);
formData.append('name', this.state.name);
formData.append('password', this.state.password);
formData.append('password', this.state.email);
axios.post('/yourEndpoint', formData).then(res => {
//Now do what you want with the response;
})
Upvotes: 1