Image upload in MERN app

 Register.js

--------------

import { useState } from "react";
import "./Register.css";
import { useForm } from "react-hook-form";
import axios from "axios";
import { useNavigate } from "react-router-dom";

function Register() {
//error state
let [error, setError] = useState("");
let [selectedFile,setSelectedFile]=useState(null)

//navigate
const navigate = useNavigate();

//use form hook
let {
register,
handleSubmit,
formState: { errors },
} = useForm();

//adding new user
let addNewUser = (newUser) => {
// console.log(newUser);
//make HTTP POST req to save newUser to localAPI

let fd=new FormData();
//append newUser to form data
fd.append("user",JSON.stringify(newUser))
//append selected file to form data
fd.append("photo",selectedFile)

axios
.post("http://localhost:4000/user-api/register-user", fd)
.then((response) => {
if (response.status === 201) {
//naviagte to login componentxp
navigate('/login')
}
if(response.status!==201){
setError(response.data.message)
}
})
.catch((err) => {
// console.log("err is ",err)
//the client was given an error response (5xx,4xx)
if (err.response) {
setError(err.message);
}
//the client never received a response
else if (err.request) {
setError(err.message);
}
//for other error
else {
setError(err.message);
}
});
};


//on file select
const onFileSelect=(e)=>{
setSelectedFile(e.target.files[0])
}


return (
<div className="add-user">
<p className="display-3 text-center">Add New User</p>
{/* form submission error */}
{error.length !== 0 && (
<p className="display-3 text-danger text-center">{error}</p>
)}
{/* add user form */}
<div className="row">
<div className="col-11 col-sm-8 col-md-6 mx-auto">
<form onSubmit={handleSubmit(addNewUser)}>
{/* username */}
<div className="mb-3">
<label htmlFor="name">Userame</label>
<input
type="text"
id="username"
className="form-control"
placeholder="e.g. John"
{...register("username", { required: true })}
/>
{/* validation errors for name */}
{errors.username?.type === "required" && (
<p className="text-danger fw-bold fs-5">
* Username is required
</p>
)}
</div>
{/* password */}
<div className="mb-3">
<label htmlFor="name">Password</label>
<input
type="password"
placeholder="*********"
id="password"
className="form-control"
{...register("password", { required: true })}
/>
{/* validation errors for name */}
{errors.password?.type === "required" && (
<p className="text-danger fw-bold fs-5">
* Password is required
</p>
)}
</div>
{/* email */}
<div className="mb-3">
<label htmlFor="name">Email</label>
<input
type="email"
placeholder="e.g. example@mail.com"
id="email"
className="form-control"
{...register("email", { required: true })}
/>
{/* validation errors for email */}
{errors.email?.type === "required" && (
<p className="text-danger fw-bold fs-5">* Email is required</p>
)}
</div>
{/* date of birth */}
<div className="mb-3">
<label htmlFor="dob">Date of birth</label>
<input
type="date"
id="dob"
className="form-control"
{...register("dob", { required: true })}
/>
{/* validation errors for name */}
{errors.dob?.type === "required" && (
<p className="text-danger fw-bold fs-5">
*Date of birth is required
</p>
)}
</div>


{/* image url */}
<div className="mb-3">
<label htmlFor="name">Select profile pic</label>
<input
type="file"
id="image"
className="form-control"
{...register("image", { required: true })}
onInput={onFileSelect}
/>
{/* validation errors for image */}
{errors.image?.type === "required" && (
<p className="text-danger fw-bold fs-5">
*Image URL is required
</p>
)}
</div>


{/* submit button */}
<button type="submit" className="btn btn-primary">
Regsiter
</button>
</form>
</div>
</div>
</div>
);
}

export default Register;




API/middlewares/cloudinaryConfig.js

----------------------------------------------

const cloudinary=require("cloudinary").v2;
const multer=require("multer");
const {CloudinaryStorage}=require("multer-storage-cloudinary");

//configure cloudinary
cloudinary.config({
cloud_name:"xxxxx",
api_key:"xxxxx",
api_secret:"xxxxxxxx"
})

//configure cloudinary storage
let clStorage=new CloudinaryStorage({
cloudinary:cloudinary,
params:{
folder:"vnr2023",
public_id:(request,file)=>file.fieldname+"-"+Date.now()
}

})

//configure multer
let multerObj=multer({storage:clStorage})

//export multerObj
module.exports=multerObj;


userApi.js

------------


//import multerObj
const multerObj=require("./middlewares/cloudinaryConfig")

//user register route
userApp.post("/register-user",multerObj.single('photo'),expressAsyncHandler(async(request,response)=>{

//get user collection
const userCollectionObj=request.app.get("userCollection")

//get user from client
const newUser=JSON.parse(request.body.user);

//verify user is already existed
const userOfDB= await userCollectionObj.findOne({username:newUser.username})

//if user already existed
if(userOfDB!==null){
response.status(200).send({message:"User already existed"})
}
//if user not existed
else{

//add CDN link of cloudinary image to user obj
newUser.image=request.file.path;
//hash the password of newUser
let hashedPassword=await bcryptjs.hash(newUser.password,6)
//replace palin password with hased password
newUser.password=hashedPassword;
//insert user
await userCollectionObj.insertOne(newUser)
//send response
response.status(201).send({message:"User created"})
}
}))

server.js

----------

//create express app
const exp = require("express");
const app = exp();
//assign port numnrt
app.listen(4000, () => console.log("server listening on port 4000..."));

const path=require("path")
//connect express with react build
app.use(exp.static(path.join(__dirname,'./build')))

//Get mongo client
const mclient=require("mongodb").MongoClient;

//connect to MongoDB server
mclient.connect('mongodb://localhost:27017/demodb')
.then(dbRef=>{
//get database obj
let dbObj=dbRef.db('demodb')
//create collection objects
let userCollection=dbObj.collection("userscollection")
let productCollection=dbObj.collection("productscollection")

//share collections objects to APIs
app.set("userCollection",userCollection)
app.set("productCollection",productCollection)

console.log("Connected to DB successfully")
})
.catch(err=>console.log("database connection err is ",err))




//import userApp and productApp
const userApp = require("./APIs/userApi");
const productApp = require("./APIs/productApi");

//forward request to userApi when url path starts with /user-api
app.use("/user-api", userApp);
//forward request to productApi when url path starts with /product-api
app.use("/product-api", productApp);


//middleware to deal with page refresh
const pageRefresh=(request,response,next)=>{
response.sendFile(path.join(__dirname,'./build/index.html'))
}
app.use("*",pageRefresh)




//create a middleware to handle invalid path
const invalidPathHandlingMiddleware = (request, response, next) => {
response.send({ message: "Invalid path" });
};

app.use(invalidPathHandlingMiddleware);

//create err handling middleware
const errHandler = (error, request, response, next) => {
response.send({ "error-message": error.message });
};
app.use(errHandler);

Comments

Popular posts from this blog