简体   繁体   中英

React, image is not uploading, getting filename is not defined error

Postman working fine with my backend code. I used form-data there and put a random file. It uploaded successfully to image folder but when it come to React , It is not uploading, and it's showing error on backend and saying filename is not defined. I don't understand the error.

React:

function Regstudent() {
  const [errorMessage, setErrorMessage] = useState("");
  let navigate = useNavigate();

  async function handleRegister(e) {
    e.preventDefault();

    const form = e.target;
    const user = {
      email: form[0].value,
      name: form[1].value,
      gender: form[2].value,
      password: form[3].value,
      batch: form[4].value,
      image: form[5].files,
    };

    try {
      const res = await fetch("http://localhost:8000/api/studentregister", {
        method: "POST",
        headers: {
          "Content-type": "application/json",
        },
        body: JSON.stringify(user),
      });
      const data = await res.json();
      setErrorMessage(data.message);
    } catch (err) {
      setErrorMessage(err);
    }
  }
  return (
    <form encType="multipart/form-data" onSubmit={(e) => handleRegister(e)}>
      <input
        placeholder="Mail Address"
        className="umail"
        type="email"
        name="email"
        id="email"
        required
      />
      <br />
      <input placeholder="Full Name" className="fname" type="text" name="name" id="name" required />
      <br />
      <input
        placeholder="Gender"
        className="gender"
        type="text"
        name="gender"
        id="gender"
        required
      />
      <br />
      <input placeholder="Password" className="password" name="password" type="password" required />
      <br />
      <select name="batch" type="select" required>
        <option value="FSD">FSD</option>
        <option value="CEH">CEH</option>
        <option value="AI">AI</option>
      </select>
      <br />
      <input type="file" accept=".png, .jpg, .jpeg" name="image" />
      <br />
      <input type="submit" className="regbutton" value="Register" />
    </form>
  );
}

Express with Multer:

//multer & uuid

const storage = multer.diskStorage({
  destination: function (req, file, cb) {
    cb(null, "images");
  },
  filename: function (req, file, cb) {
    cb(null, uuidv4() + "-" + Date.now() + path.extname(file.originalname));
  },
});

const fileFilter = (req, file, cb) => {
  const allowedFileTypes = ["image/jpeg", "image/jpg", "image/png"];
  if (allowedFileTypes.includes(file.mimetype)) {
    cb(null, true);
  } else {
    cb(null, false);
  }
};

let upload = multer({ storage, fileFilter });

//POST
app.post("/api/studentregister", upload.single("image"), async (req, res) => {
  const user = req.body;

  //check user name or pswd is taken before
  const takenEmail = await Users.findOne({ email: user.email });
  const regex = /^[^\s@]+@[^\s@]+\.[^\s@]{2,}$/i;

  if (takenEmail) {
    res.json({ message: "Email has already been taken" });
  } else if (!regex.test(user.email)) {
    res.json({ message: "Email is invalid" });
  } else {
    user.password = await bcrypt.hash(req.body.password, 10);
    const dbUser = new Users({
      email: user.email.toLowerCase(),
      name: user.name,
      gender: user.gender,
      password: user.password,
      batch: user.batch,
      image: req.file.filename,
      role: "user",
    });
    dbUser.save();
    res.json({ message: "Success" });
  }
});

An easy way to send files with fetch is to use theFormData() , which allows to create and send multipart/form-data . Like so:

Notice I'm giving the HTML form to FormData through e.target . This will populate its fields inside formData . And also, notice there is no Content-type defined.

async function handleRegister(e) {
  e.preventDefault();
  const formData = new FormData(e.target);
  try {
    const res = await fetch("http://localhost:8000/api/studentregister", {
      method: "POST",
      body: formData,
    });
    const data = await res.json();
    setErrorMessage(data.message);
  } catch (err) {
    setErrorMessage(err);
  }
}

I had a similar issue, after hours of finding a solution, this helped send the files to backend. ...

const formData=new FormData();
formData.append("fileName",data)

   try {
      const res = await fetch("your api url", {
        method: "POST",
        body: fileData,
      });
      const data = await res.json();
      setErrorMessage(data.message);
    } catch (err) {
      setErrorMessage(err);
    }
  }

...

Ps Header should be empty.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM