在 MERN 应用程序中,对节点的 API 请求通过反应仅获取响应如果在从反应发出 API 请求后刷新节点服务器

问题描述 投票:0回答:0

MERN应用程序当我在POSTMAN中测试时一切正常。

如果您使用 POSTMAN 选择视频 file。你会在response 中得到正确的错误只有图像应该上传这是预期的

但是在 sending 请求之后使用 react 尝试了同样的事情,没有得到任何回报,代码在 react 中的获取请求停止运行

如果你重新启动节点 server 只有这样你才能 response 回到 reactApp.

注意-仅在上传视频时出现此问题。其他格式文件给我回复很好。

注意 - 登录用户的数据已经存储在 req.user

NODE server =  http://localhost:4000
React Url = http://localhost:5173

server.js

app.use('/user' UserRoute)


**UserController.Js**

const AppError = require("../utils/appError");
const User = require("../model/userModel");
const catchAsync = require("../utils/catchError");
const handlerFactory = require("./handlerFactory");
const multer = require("multer");
const cloudinary = require("cloudinary").v2;


cloudinary.config({
  cloud_name: process.env.CLOUD_NAME,
  api_key: process.env.API_KEY,
  api_secret: process.env.API_SECRET,
});



exports.getMe = async (req, res, next) => {
  req.params.id = req.user.id;
  next();
};


exports.passwordAndEmailCheck = catchAsync(async (req, res, next) => {
  if (
    req.body.password ||
    req.body.confirmPassword ||
    req.body.passwordChangeAt ||
    req.body.email
  ) {
    return next(
      new AppError(
        "To update password or email use /users/update-password/ or /users/update-email/ route",
        404
      )
    );
  }



const multerFilter = (req, file, cb) => {
  if (file.mimetype.startsWith("image")) {
    console.log("Valid File")
    return cb(null, true);
  } else {
  console.log("Not a valid File")

    return cb(
      new AppError("Not an image! Please upload only images.", 400),
      false
    );
  }
};

const upload = multer({
  storage: multer.diskStorage({}),
  fileFilter: multerFilter,
});


exports.uploadUserPhoto = upload.single("image");

exports.hashImageUrl = catchAsync(async (req, res, next) => {
  if (!req.file) {
    return next();
  }
  if (req.file.size > 5 * 1024 * 1024)
    return next(
      new AppError(`Please upload a file with size less than 5MB!`, 400)
  );
  const publicId = req.user.publicId;
  if (publicId) {
    await cloudinary.uploader.destroy(publicId);
  }

  const result = await cloudinary.uploader.upload(req.file.path, {
    folder: "user-images",
    format: "jpg",
    transformation: [
      { width: 400, height: 400, crop: "fill", gravity: "face", quality: 90 },
    ],
  });

  req.user.publicId = result.public_id;
  req.user.imageUrl = result.secure_url;
  next();
});

exports.updateUserDetails =>
  catchAsync(async (req, res, next) => {
    const doc = await User.findByIdAndUpdate(req.params.id, {...req.body, image:req.user.imageUrl, publicId:req.user.publicId}, {
      new: true,
      runValidators: true,
    })

    if (!doc) {
      next(new AppError(`Invalid user ID`, 404));
      return;
    }

    res.status(201).json({
      status: "success",
      data: doc,
    });
  });

```

```
Update User Routes

router.patch(
  "/update-details",
  userController.getMe,
  userController.passwordAndEmailCheck,
  userController.uploadUserPhoto,
  userController.hashImageUrl,
  userController.updateUserDetails
);

```


```
UserModel.js

const mongoose = require("mongoose");
const bcrypt = require("bcrypt");
const crypto = require("crypto");
const validator = require("validator");

const User = new mongoose.Schema({
  name: {
    type: String,
    required: [true, "name is required"],
    maxLength: [50, "name should be upto 50 characters"],
    trim: true,
  },
  email: {
    type: String,
    required: [true, "email is required"],
    unique: [true, "email should be unique"],
    lowercase: true,
    validate: [validator.isEmail, "Please provide a valid email"],
  },
  image: {
    type: String,
    default:"default.jpg"
  },
  publicId:{
    type:String
  },
  role: {
    type: String,
    enum: ["admin", "user", "guide", "lead-guide"],
    default: "user",
  },
  password: {
    type: String,
    required: [true, "A password is required"],
    minLenght: [8, "A password must have minimum length of 8 characters"],
    select: false,
  },
  confirmPassword: {
    type: String,
    required: [true, "A password is required"],
    minLenght: [8, "A password must have minimum length of 8 characters"],
    validate: {
      validator: function (el) {
        return el === this.password;
      },
      messsage: "Passwords doesn't match",
    },
  },
  passwordChangeAt: {
    type: Date,
  },
  passwordResetToken: String,
  resetTokenExpiresIn: Date,
  active: {
    type: Boolean,
    select: false,
    default: true,
  },
});

module.exports = mongoose.model("users", User);

```


```
**AppError.js**


class AppError extends Error{
    constructor(message, statusCode){
        super(message)
        this.statusCode = statusCode
        this.status = `${statusCode}`.startsWith("4")?"fail":"error"
        this.isOperational = true
        Error.captureStackTrace(this, this.constructor)
    }
}

module.exports = AppError
```

```
CatchAsync.js

module.exports = fn => {
    return (req, res, next) => {
      fn(req, res, next).catch(next);
    };
  };
```

**REACT CODE**

API URL = http://localhost:4000/users/update-details
 

```
import { useState } from "react";
import Cookies from "js-cookie";
const Form = () => {
  const [name, setName] = useState("");
  const [photo, setPhoto] = useState(null);
  const [sending, setSending] = useState(false)

  const handleSubmit = async (e) => {
    e.preventDefault();
    setSending(true)
    const jwtToken = Cookies.get("jwtToken");

    const formData = new FormData();
      formData.append("image", photo);
      const res = await fetch("http://localhost:4000/users/update-details", {
        method: "PATCH",
        body: formData,
        headers: {
          Authorization: `Bearer ${jwtToken}`,
        },
      });
      console.log(res)
      const data = await res.json();
      setSending(false)
    };

  return (
    <div className="form-cont">
      <h1 className="h1">FORM</h1>
      <form className="form" onSubmit={handleSubmit}>
        <input
          type="text"
          name="name"
          value={name}
          onChange={(e) => setName(e.target.value)}
        />
        <input
          type="file"
          name="photo"
          accept="image/*"
          onChange={(e) => {
            setPhoto(e.target.files[0]);
          }}
        />
        <button className="button" type="submit">
          Submit
        </button>
        {sending && <h1>Sending....</h1>}
      </form>
    </div>
  );
};

export default Form;
```


New to node haven't tried much just some console.log's
multipartform-data multer cloudinary node-api react-fetch-api
© www.soinside.com 2019 - 2024. All rights reserved.