skip to Main Content

I am using multer and cloudinary for backend to upload image to mongodb and getting req.file.path error and it seems I’m doing something wrong in the frontend when passing image because if I use POSTMAN, the api works and sign ups the user with image as a link.

Backend Code:

controller.js

const jwt = require("jsonwebtoken");
const bcrypt = require("bcryptjs");
const asyncHandler = require("express-async-handler");
const User = require("../models/userModel");

const registerUser = asyncHandler(async (req, res) => {
  const { proImg, role, firstName, lastName, email, password } = req.body;

  if (!firstName || !lastName || !email || !password) {
    res.status(400);
    throw new Error("Please add all the required fields");
  }

  //Check if the emails already exist
  const userExists = await User.findOne({ email });
  const sellerExists = await Seller.findOne({ email });
  if (userExists || sellerExists) {
    res.status(400);
    throw new Error("Email already exists");
  }

  //Hash passwords
  const salt = await bcrypt.genSalt(10);
  const hashedPassword = await bcrypt.hash(password, salt);

  //Create user
  const user = await User.create({
    proImg: req.file.path, //Getting error on this line
    role,
    firstName,
    lastName,
    email,
    password: hashedPassword,
  });

  if (user) {
    res.status(201).json({
      _id: user.id,
      proImg: user.proImg,
      role: user.role,
      firstName: user.firstName,
      lastName: user.lastName,
      email: user.email,
      token: generateToken(user._id),
    });
  } else {
    res.status(400);
    throw new Error("Invalid user data");
  }
});

cloudinary.config.js

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

  const { CLOUDINARY_API, CLOUDINARY_SECRET, CLOUDINARY_HOST } = process.env;
  cloudinary.config({
    cloud_name: CLOUDINARY_HOST,
    api_key: CLOUDINARY_API,
    api_secret: CLOUDINARY_SECRET,
  });

  const storage = new CloudinaryStorage({
    cloudinary: cloudinary,
    params: {
      folder: "images",
      format: async () => "png",
      public_id: (req, file) => file.filename,
    },
  });

  const parser = multer({ storage: storage });

  module.exports = parser;

Frontend:

SignupBuyer.jsx

const [data, setData] = useState({
    proImg: "",
    role: "buyer",
    firstName: "",
    lastName: "",
    email: "",
    password: "",
    cPassword: "",
  });

  const { proImg, role, firstName, lastName, email, password, cPassword } =
    data;

  const navigate = useNavigate();
  const dispatch = useDispatch();

  const { user, isLoading, isSuccess, isError, message } = useSelector(
    (state) => state.auth
  );

  useEffect(() => {
    if (isError) toast.error(message);

    if (isSuccess || user) {
      navigate("/buyerdashboard");
    }

    dispatch(reset());
  }, [user, isError, isSuccess, message, navigate, dispatch]);

  //Toggle password display
  const [passwordShown, setPasswordShown] = useState(false);
  const togglePassword = () => {
    setPasswordShown(!passwordShown);
  };

  const handleImage = (e) => {
    setData((prevState) => ({
      ...prevState,
      proImg: e.target.files[0],
    }));

    console.log(e.target.files[0]);
  };

  const handleChange = (e) => {
    setData((prevState) => ({
      ...prevState,
      [e.target.name]: e.target.value,
    }));
  };

  const handleSubmit = (e) => {
    e.preventDefault();
    if (password !== cPassword) {
      toast.error("Passwords do not match");
    } else {
      const userData = { proImg, role, firstName, lastName, email, password };

      dispatch(register(userData));
    }
  };

  if (isLoading) return <Spinner />;

  return (
    <>
      <div className="signup">
        <div className="signup__container">
          <h3>Join Us to Hire Talent</h3>
          <form
            className="signup__container-form"
            encType="multipart/form-data"
            onSubmit={handleSubmit}
          >
            <input
              type="file"
              accept=".png, .jpeg, .jpg"
              name="proImg"
              onChange={handleImage}
            />

2

Answers


  1. Chosen as BEST ANSWER

    Ok so I fixed the error I was getting and got the expected result. For anyone having a similar problem, I had to change the handleSubmit from the frontend from:

        const handleSubmit = (e) => {
        e.preventDefault();
        if (password !== cPassword) {
          toast.error("Passwords do not match");
        } else {
          const userData = { proImg, role, firstName, lastName, email, password };
    
          dispatch(register(userData));
        }
      };
    

    To this:

        const handleSubmit = (e) => {
        e.preventDefault();
        if (password !== cPassword) {
          toast.error("Passwords do not match");
        } else {
          const userData = new FormData();
          userData.append("proImg", proImg);
          userData.append("role", role);
          userData.append("firstName", firstName);
          userData.append("lastName", lastName);
          userData.append("email", email);
          userData.append("password", password);
    
          dispatch(register(userData));
        }
      };
    

  2. Since your input type has a name property as proImg, looks like you need to specify req.proImg as shown below:

    proImg: req.proImg.path
    
        <input type="file" accept=".png, .jpeg, .jpg" **name="proImg"** onChange={handleImage}/>
    
    Login or Signup to reply.
Please signup or login to give your own answer.
Back To Top
Search