In this tutorial, we are going to learn how to upload a single file in React app. We will also learn to store image files in the MongoDB database using the Node server. Uploading image files is a day to day task of a web developer, if you are new to React, then this tutorial has the answer which you are looking for.
We will learn to upload single image file and store that file in the MongoDB database using Node and React.js. We will learn to create a client-side basic React app, along with that we will also create a file upload API with Express, Multer, and other Node packages.
In the very first step, we install and set up React app for file upload demo.
Enter the following command in your terminal and press enter.
create-react-app react-node-file-upload
Go to the project folder:
cd react-node-file-upload
Start your React app in the web browser:
npm start
View project on this URL: localhost:3000
Install Bootstrap 4 in React app.
npm install bootstrap --save
Include bootstrap.min.css in src/App.js file:
import React from 'react';
import '../node_modules/bootstrap/dist/css/bootstrap.min.css';
function App() {
return (
<div className="App">
<h2>React File Upload Demo</h2>
</div>
);
}
export default App;
Head over to src > components directory and create a separate file by the name of files-upload-component.js.
import React, { Component } from 'react';
export default class FilesUploadComponent extends Component {
render() {
return (
<div className="container">
<div className="row">
<form>
<h3>React File Upload</h3>
<div className="form-group">
<input type="file" />
</div>
<div className="form-group">
<button className="btn btn-primary" type="submit">Upload</button>
</div>
</form>
</div>
</div>
)
}
}
Add FilesUploadComponent in App.js template.
import React, { Component } from 'react';
import '../node_modules/bootstrap/dist/css/bootstrap.min.css';
import './App.css';
import FilesUploadComponent from './components/files-upload-component';
class App extends Component {
render() {
return (
<div className="App">
<FilesUploadComponent />
</div>
);
}
}
export default App;
Let’s build the server with Node, Express, MongoDB and Multer for React file upload tutorial. Create the backend folder inside the React project.
Execute command to generate backend folder and get into the project folder.
mkdir backend && cd backend
Build separate package.json file for Node server.
npm init
We will use following node modules to build Node/Express server:
Run command to install NPM packages:
npm install mongoose express cors body-parser uuid multer
Install nodemon to auto-restart the node server, whenever it detects change in the server files.
Create a backend > database folder and create a new file inside of it by the name of db.js.
module.exports = {
db: 'mongodb://localhost:27017/react-fileupload-db'
};
Create a backend > models directory and create a fresh file inside of it and name it User.js.
const mongoose = require('mongoose');
const Schema = mongoose.Schema;
const userSchema = new Schema({
_id: mongoose.Schema.Types.ObjectId,
profileImg: {
type: String
}
}, {
collection: 'users'
})
module.exports = mongoose.model('User', userSchema)
We declared profileImg value with String data type along with Mongoose _id in Mongoose schema file.
Create a backend > routes folder and create a new file inside of it and name it user.routes.js.
Create backend > public folder, in this folder we will store all the image files uploaded by user.
Run command from the root of the backend project.
mkdir public
let express = require('express'),
multer = require('multer'),
mongoose = require('mongoose'),
uuidv4 = require('uuid/v4'),
router = express.Router();
const DIR = './public/';
const storage = multer.diskStorage({
destination: (req, file, cb) => {
cb(null, DIR);
},
filename: (req, file, cb) => {
const fileName = file.originalname.toLowerCase().split(' ').join('-');
cb(null, uuidv4() + '-' + fileName)
}
});
var upload = multer({
storage: storage,
fileFilter: (req, file, cb) => {
if (file.mimetype == "image/png" || file.mimetype == "image/jpg" || file.mimetype == "image/jpeg") {
cb(null, true);
} else {
cb(null, false);
return cb(new Error('Only .png, .jpg and .jpeg format allowed!'));
}
}
});
// User model
let User = require('../models/User');
router.post('/user-profile', upload.single('profileImg'), (req, res, next) => {
const url = req.protocol + '://' + req.get('host')
const user = new User({
_id: new mongoose.Types.ObjectId(),
name: req.body.name,
profileImg: url + '/public/' + req.file.filename
});
user.save().then(result => {
res.status(201).json({
message: "User registered successfully!",
userCreated: {
_id: result._id,
profileImg: result.profileImg
}
})
}).catch(err => {
console.log(err),
res.status(500).json({
error: err
});
})
})
router.get("/", (req, res, next) => {
User.find().then(data => {
res.status(200).json({
message: "User list retrieved successfully!",
users: data
});
});
});
module.exports = router;
In this step, create a backend > server.js file and paste the following code in it. This file contains required server settings such as database, express configuration, PORT connection, etc
let express = require('express'),
mongoose = require('mongoose'),
cors = require('cors'),
bodyParser = require('body-parser'),
dbConfig = require('./database/db');
const api = require('../backend/routes/user.routes')
// MongoDB Configuration
mongoose.Promise = global.Promise;
mongoose.connect(dbConfig.db, {
useNewUrlParser: true
}).then(() => {
console.log('Database sucessfully connected')
},
error => {
console.log('Database could not be connected: ' + error)
}
)
const app = express();
app.use(bodyParser.json());
app.use(bodyParser.urlencoded({
extended: false
}));
app.use(cors());
app.use('/public', express.static('public'));
app.use('/api', api)
const port = process.env.PORT || 4000;
const server = app.listen(port, () => {
console.log('Connected to port ' + port)
})
app.use((req, res, next) => {
// Error goes via `next()` method
setImmediate(() => {
next(new Error('Something went wrong'));
});
});
app.use(function (err, req, res, next) {
console.error(err.message);
if (!err.statusCode) err.statusCode = 500;
res.status(err.statusCode).send(err.message);
});
In this step we will test REST API which we just created, before that we need to start the Node server. Follow the given below process to start the Node/Express server.
Run command to start the mongoDB.
mongod
Run nodemon server by executing the following command:
nodemon server
API base Url: http://localhost:4000/api
We can test following API in Postman, below is the final result:
Let’s build React File upload functionality, first install the React axios library.
Next, install Axios library, it helps in making Http request in React app.
npm install axios
Add the below code in src/components/files-upload.component.js file.
import React, { Component } from 'react';
import axios from 'axios';
export default class FilesUploadComponent extends Component {
constructor(props) {
super(props);
this.onFileChange = this.onFileChange.bind(this);
this.onSubmit = this.onSubmit.bind(this);
this.state = {
profileImg: ''
}
}
onFileChange(e) {
this.setState({ profileImg: e.target.files[0] })
}
onSubmit(e) {
e.preventDefault()
const formData = new FormData()
formData.append('profileImg', this.state.profileImg)
axios.post("http://localhost:4000/api/user-profile", formData, {
}).then(res => {
console.log(res)
})
}
render() {
return (
<div className="container">
<div className="row">
<form onSubmit={this.onSubmit}>
<div className="form-group">
<input type="file" onChange={this.onFileChange} />
</div>
<div className="form-group">
<button className="btn btn-primary" type="submit">Upload</button>
</div>
</form>
</div>
</div>
)
}
}
We declared the constructor and set the profileImg state and bind the events.
Inside the file input field, we passed the onChange event along with onSubmit method on the form.
In the onSubmit method, we manage the file value using FormData interface, and then we are making the HTTP POST request using the Axios post() method.
In this tutorial, we learned to upload a single file in React app and store the images in the MongoDB database using the Node server.
#react #node #javascript