I am trying to create a register page where the user has to upload profile photo. All the fields of the form data are being read properly but the multer upload to local directory is not functioning and the req.file which should store the file is not getting populated.
upload.js for multer
import multer from "multer";
const storage = multer.diskStorage({
destination: function (req, file, cb) {
cb(null, "./public/temp")
},
filename: function (req, file, cb) {
cb(null, file.originalname)
}
})
export const upload = multer({
storage,
})
student which is the user router file
import express from 'express';
import {upload} from '../middlewares/multer.js';
import { isAuthorized } from '../middlewares/auth.js';
import {registerStudent,loginStudent,logoutStudent,changePassword, getStudentProfile} from "../controllers/studentController.js"
const router = express.Router();
router.route("/register").post(
upload.single("profilePhoto"),
registerStudent
);
router.route("/login").post(loginStudent)
router.route("/logout").post(isAuthorized,logoutStudent)
router.route("/changePassword").post(isAuthorized,changePassword)
router.route("/details").get(isAuthorized,getStudentProfile)
export default router;
Register function of the student controller
export const registerStudent = catchAsyncError( async (req, res) => {
const {name,email,password,phone,branch,courseName,yearOfStudy,CGPA,address} = req.body
if(!name || !email || !phone || !courseName || !branch|| !password || !yearOfStudy ||!CGPA ||!address) {
throw new ErrorHandler("Please enter all the fields", 400);
}
const isEmail = await Student.findOne({email});
if (isEmail) {
throw new ErrorHandler("Student already exists with this email", 400);
}
//cgpa validation
if (CGPA < 0 || CGPA > 10) {
throw new ErrorHandler("CGPA must be between 0 and 10", 400);
}
let profilePhotoURLLocalPath;
if(req.file){
console.log(req.file);
profilePhotoURLLocalPath = req.file;
}
if (!profilePhotoURLLocalPath) {
throw new ErrorHandler("Please upload your profile photo",401)
}
const profilePhoto = await uploadOnCloudinary(profilePhotoURLLocalPath);
if (!profilePhoto) {
throw new ErrorHandler("Error while uploading profile photo",500);
}
const student = await Student.create({
name,
email,
password,
phone,
branch,
courseName,
yearOfStudy,
CGPA,
address,
profilePhoto: profilePhoto.url
})
return res.status(201).json({
success: true,
message : "Student registered successfully",
student
})
} )
Front end form data populating
import React, { useEffect, useState } from "react";
import axios from "axios";
import toast from "react-hot-toast";
const StudentRegister = () => {
const [name, setName] = useState("");
const [email, setEmail] = useState("");
const [password, setPassword] = useState("");
const [phone, setPhone] = useState("");
const [branch, setBranch] = useState("");
const [courseName, setCourseName] = useState("");
const [yearOfStudy, setYearOfStudy] = useState("");
const [address, setAddress] = useState("");
const [cgpa, setCgpa] = useState("");
const [profilePhoto, setImage] = useState("");
const handleFileUpload = (e) => {
const image = e.target.files[0];
setImage(image);
};
const handleRegister = async (e) => {
e.preventDefault();
console.log(profilePhoto);
let temp = new FormData();
temp.append("name", name);
temp.append("email", email);
temp.append("password", password);
temp.append("phone", phone);
temp.append("branch", branch);
temp.append("courseName", courseName);
temp.append("yearOfStudy", yearOfStudy);
temp.append("address", address);
temp.append("CGPA", cgpa);
temp.append("profilePhoto", profilePhoto);
try {
const resp = await axios.post(
"http://localhost:4000/api/v1/student/register",
temp,
{
withCredentials: true,
headers: {
"Content-Type": "application/json",
},
}
);
toast.success(resp.data.message);
setName("");
setEmail("");
setPassword("");
setPhone("");
setBranch("");
setCourseName("");
setYearOfStudy("");
setAddress("");
setCgpa("");
setAvatar("");
} catch (err) {
toast.error(err.response.data.message);
}
};
return (
<form method="POST" action="/api/v1/student/register" enctype="multipart/form-data">
<input
type="text"
placeholder="Name"
value={name}
onChange={(e) => setName(e.target.value)}
/>
<input
type="email"
placeholder="Email"
value={email}
onChange={(e) => setEmail(e.target.value)}
/>
<input
type="password"
placeholder="Password"
value={password}
onChange={(e) => setPassword(e.target.value)}
/>
<input
type="tel"
placeholder="Phone"
value={phone}
onChange={(e) => setPhone(e.target.value)}
/>
<input
type="text"
placeholder="Branch"
value={branch}
onChange={(e) => setBranch(e.target.value)}
/>
<input
type="text"
placeholder="Course Name"
value={courseName}
onChange={(e) => setCourseName(e.target.value)}
/>
<input
type="text"
placeholder="Year of Study"
value={yearOfStudy}
onChange={(e) => setYearOfStudy(e.target.value)}
/>
<input
type="text"
placeholder="Address"
value={address}
onChange={(e) => setAddress(e.target.value)}
/>
<input
type="text"
placeholder="CGPA"
value={cgpa}
onChange={(e) => setCgpa(e.target.value)}
/>
<input id="file-upload" name="profilePhoto" type="file" accept=".png, .jpeg" onChange={handleFileUpload}/>
<button type="submit" onClick={handleRegister}>
Register
</button>
</form>
);
};
export default StudentRegister;
App.js
import express from 'express';
import dotenv from 'dotenv';
import cors from 'cors';
import cookieParser from 'cookie-parser';
import alumniRouter from './routes/alumniRouter.js';
import studentRouter from './routes/studentRouter.js';
import companyRouter from './routes/companyRouter.js';
import applicationRouter from './routes/applicationRouter.js';
import jobRouter from './routes/jobRouter.js';
import {dbConnection} from './database/dbConnection.js';
import {errorMiddleware} from './middlewares/error.js';
import adminRouter from './routes/adminRouter.js';
import { upload } from './middlewares/multer.js';
const app = express();
dotenv.config({path: "./config/config.env"});
app.use(cors({
origin: process.env.FRONTEND_URL,
methods: ["GET", "POST","DELETE","PUT"],
credentials: true,
}));
dbConnection();
app.use(cookieParser());
app.use(express.json());
app.use(express.urlencoded({extended: true}));
app.use('/api/v1/alumni', alumniRouter);
app.use('/api/v1/student',studentRouter);
app.use('/api/v1/company', companyRouter);
app.use('/api/v1/job', jobRouter);
app.use('/api/v1/admin', adminRouter);
app.use('/api/v1/application', applicationRouter);
app.use(errorMiddleware);
export default app;
The req.file remains undefined and hence the error to Upload profile photo keeps popping
I tried all possible solutions to other similar questions. Some said to add multer upload as first middleware but it seems to be first in my case already.