Не удается получить данные формы в req.body Express / node. js - PullRequest
1 голос
/ 02 августа 2020

Я пытаюсь создать электронную регистрацию для нового пользователя с загрузкой изображения профиля. Но данные моей формы не передаются в маршрут. Я добавил промежуточное ПО для body-parser, но все же кажется, что что-то не так, и я не могу найти причину.

Ошибка:

D:\temp_project\smpms\routes\users.js:118
                        if (err) throw err;
                                 ^

Error: Illegal arguments: undefined, string
    at _async (D:\temp_project\smpms\node_modules\bcryptjs\dist\bcrypt.js:214:46)
    at Object.bcrypt.hash (D:\temp_project\smpms\node_modules\bcryptjs\dist\bcrypt.js:220:13)
    at D:\temp_project\smpms\routes\users.js:117:28
    at Immediate.<anonymous> (D:\temp_project\smpms\node_modules\bcryptjs\dist\bcrypt.js:153:21)
    at processImmediate (internal/timers.js:456:21)
[nodemon] app crashed - waiting for file changes before starting...

app. js

const express = require("express");
const expressLayouts = require("express-ejs-layouts");
const mongoose = require("mongoose");
const passport = require("passport");
const flash = require("connect-flash");
const session = require("express-session");
const multer = require('multer');
const path = require('path');
var dotenv = require('dotenv').config();
const bodyParser =  require('body-parser');
const app = express();
// parse application/x-www-form-urlencoded
app.use(bodyParser.urlencoded({ extended: false }))

// parse application/json
app.use(bodyParser.json())
app.use(express.static("public"));

// Passport Config
require("./config/passport")(passport);

// DB Config
const db = require("./config/keys").mongoURI;

// Connect to MongoDB
mongoose
  .connect(db, { useNewUrlParser: true, useUnifiedTopology: true })
  .then(() => console.log("MongoDB Connected"))
  .catch((err) => console.log(err));

// EJS
app.use(expressLayouts);
app.set("view engine", "ejs");

// Express body parser
app.use(express.urlencoded({ extended: true }));

// Express session
app.use(
  session({
    secret: "secret",
    resave: true,
    saveUninitialized: true,
  })
);

// Passport middleware
app.use(passport.initialize());
app.use(passport.session());

// Connect flash
app.use(flash());

// Global variables
app.use(function (req, res, next) {
  res.locals.success_msg = req.flash("success_msg");
  res.locals.error_msg = req.flash("error_msg");
  res.locals.error = req.flash("error");
  next();
});

// Routes
app.use("/", require("./routes/index.js"));
app.use("/users", require("./routes/users.js"));

const PORT = process.env.PORT || 5000;

app.listen(PORT, console.log(`Server started on port ${PORT}`));

Пользователь. js - Модель пользователя

const mongoose = require('mongoose');

const UserSchema = new mongoose.Schema({
  name: {
    type: String,
    required: true
  },
  email: {
    type: String,
    required: true
  },
  password: {
    type: String,
    required: true
  },
  avatar:{
    type:String,
    required:true
  },
  date: {
    type: Date,
    default: Date.now
  }
});

const User = mongoose.model('User', UserSchema);

module.exports = User;

Пользователь. js маршрут:

const express = require("express");
const router = express.Router();
const bcrypt = require("bcryptjs");
const passport = require("passport");
const multer = require('multer');
const path = require('path');
const bodyParser = require('body-parser')
const app = express()
// parse application/x-www-form-urlencoded
app.use(bodyParser.urlencoded({ extended: false }))

// parse application/json
app.use(bodyParser.json())
// Load User model
const User = require("../models/User");
const {forwardAuthenticated} = require("../config/auth");


// Login Page
router.get("/login", forwardAuthenticated, (req, res) => {
    res.render("login", {title: "Login", layout: "layout"});
});

// Register Page
router.get("/register", forwardAuthenticated, (req, res) => {
    res.render("register", {title: "Register", layout: "layout"});
});

// Register
router.post("/register", (req, res) => {
    //const {name, email, password, password2||avatar} = req.body;
    const name = req.body.name
    const email = req.body.email
    const password = req.body.password;
    const password2 = req.body.password2;
    const avatar = req.body.avatar;

    let errors = [];
    //
    // if (!name || !email || !password || !password2) {
    //     errors.push({msg: "Please enter all fields"});
    // }
    // if (password && password.length < 6) {
    //     errors.push({msg: "Password must be at least 6 characters"});
    // }
    // if (password != password2) {
    //     errors.push({msg: "Passwords do not match"});
    // }

    if (errors.length > 0) {
        res.render("register", {
            errors,
            name,
            email,
            password,
            password2,
            title: "Register",
            layout: "Layout",
        });
    } else {
        User.findOne({email: email}).then((user) => {
            if (user) {
                errors.push({msg: "Email already exists"});
                res.render("register", {
                    errors,
                    name,
                    email,
                    password,
                    password2,
                    title: "Register",
                    layout: "Layout",
                });
            } else {
                const newUser = new User({
                    name,
                    email,
                    password,
                });
                //Set The Storage Engine
                const storage = multer.diskStorage({
                    destination: './public/uploads/',
                    filename: function (req, file, cb) {
                        cb(null, file.fieldname + '-' + newUser._id + path.extname(file.originalname));
                    }
                });

                // Init Upload
                const upload = multer({
                    storage: storage,
                    limits: {fileSize: 1000000},
                    fileFilter: function (req, file, cb) {
                        checkFileType(file, cb);
                    }
                }).single('avatar');

                // Check File Type
                function checkFileType(file, cb) {
                    // Allowed ext
                    const filetypes = /jpeg|jpg|png|gif/;
                    // Check ext
                    const extname = filetypes.test(path.extname(file.originalname).toLowerCase());
                    // Check mime
                    const mimetype = filetypes.test(file.mimetype);

                    if (mimetype && extname) {
                        return cb(null, true);
                    } else {
                        cb('Error: Images Only!');
                    }
                }


                console.log(newUser);
                newUser.avatar = storage;
                console.log(newUser);
                bcrypt.genSalt(10, (err, salt) => {
                    bcrypt.hash(newUser.password, salt, (err, hash) => {
                        if (err) throw err;
                        newUser.password = hash;
                        newUser
                            .save()
                            .then((user) => {
                                req.flash(
                                    "success_msg",
                                    "You are now registered and can log in"
                                );
                                res.redirect("/users/login");
                            })
                            .catch((err) => console.log(err));
                    });
                });
            }
        });
    }
});

// Login
router.post("/login", (req, res, next) => {
    passport.authenticate("local", {
        successRedirect: "/dashboard",
        failureRedirect: "/users/login",
        failureFlash: true,
    })(req, res, next);
});

// Logout
router.get("/logout", (req, res) => {
    req.logout();
    req.flash("success_msg", "You are logged out");
    res.redirect("/users/login");
});

module.exports = router;

Зарегистрироваться. e js - это файл, в котором форма не передает данные в маршрут.

<div class="row mt-5">
  <div class="col-md-6 m-auto">
    <div class="card card-body">
      <h1 class="text-center mb-3">
        <i class="fas fa-user-plus"></i> Register
      </h1>
      <% include ./partials/messages %>
      <%= typeof msg != 'undefined' ? msg : '' %>
      <form action="/users/register" method="POST" enctype="multipart/form-data">
        <div class="form-group">
          <label for="name">Name</label>
          <input
            type="name"
            id="name"
            name="name"
            class="form-control"
            placeholder="Enter Name"
            value="<%= typeof name != 'undefined' ? name : '' %>"
          />
        </div>
        <div class="form-group">
          <label for="email">Email</label>
          <input
            type="email"
            id="email"
            name="email"
            class="form-control"
            placeholder="Enter Email"
            value="<%= typeof email != 'undefined' ? email : '' %>"
          />
        </div>
        <div class="form-group">
          <label for="password">Password</label>
          <input
            type="password"
            id="password"
            name="password"
            class="form-control"
            placeholder="Create Password"
            value="<%= typeof password != 'undefined' ? password : '' %>"
          />
        </div>
        <div class="form-group">
          <label for="password2">Confirm Password</label>
          <input
            type="password"
            id="password2"
            name="password2"
            class="form-control"
            placeholder="Confirm Password"
            value="<%= typeof password2 != 'undefined' ? password2 : '' %>"
          />
        </div>
        <div class="form-group">
          <label for="">Profile Picture</label>
          <input type="file" name="avatar" id="" class="form-control  file-path validate">
        </div>
        <button type="submit" class="btn btn-primary btn-block">
          Register
        </button>
      </form>
      <p class="lead mt-4">Have An Account? <a href="/users/login">Login</a></p>
    </div>
  </div>
</div>

1 Ответ

1 голос
/ 02 августа 2020

Похоже, вы неправильно используете multer. Обычно конфигурация multer устанавливается глобально и, прежде всего, для всех API-интерфейсов, а затем мы передаем эту функцию промежуточного программного обеспечения, сгенерированную multer, этому определенному c API, который имеет заголовок multipart/form-data в своем запросе. Вы должны переместить свою конфигурацию для multer за пределы вашего API, а затем передать upload в качестве промежуточного программного обеспечения для вашего API. Также со стороны вашего клиента вы должны правильно передавать данные. Хороший ответ об отправке JSON вместе с объектом FormData можно найти здесь . Также вы можете добавить текстовые поля в объект FormData со стороны клиента и получить его как объект в req.body в соответствии с документацией multer. Просто убедитесь, что вы правильно передаете данные со стороны клиента на сервер. Вот ваш маршрутизатор с multer промежуточным программным обеспечением:

const express = require("express");
const router = express.Router();
const fs = require('fs');
const bcrypt = require("bcryptjs");
const passport = require("passport");
const multer = require('multer');
const path = require('path');
const bodyParser = require('body-parser')
const app = express()
// parse application/x-www-form-urlencoded
app.use(bodyParser.urlencoded({ extended: false }))

// parse application/json
app.use(bodyParser.json())
// Load User model
const User = require("../models/User");
const { forwardAuthenticated } = require("../config/auth");


// Login Page
router.get("/login", forwardAuthenticated, (req, res) => {
    res.render("login", { title: "Login", layout: "layout" });
});

// Register Page
router.get("/register", forwardAuthenticated, (req, res) => {
    res.render("register", { title: "Register", layout: "layout" });
});

const storage = multer.diskStorage({
    destination: './public/uploads/'
});

// Init Upload
const upload = multer({
    storage: storage,
    limits: { fileSize: 1000000 },
    fileFilter: function (req, file, cb) {
        checkFileType(file, cb);
    }
});

// Check File Type
function checkFileType(file, cb) {
    // Allowed ext
    const filetypes = /jpeg|jpg|png|gif/;
    // Check ext
    const extname = filetypes.test(path.extname(file.originalname).toLowerCase());
    // Check mime
    const mimetype = filetypes.test(file.mimetype);

    if (mimetype && extname) {
        return cb(null, true);
    } else {
        cb('Error: Images Only!');
    }
}
// Register
router.post("/register", upload.single('avatar'), (req, res) => {
    //const {name, email, password, password2||avatar} = req.body;
    const name = req.body.name
    const email = req.body.email
    const password = req.body.password;
    const password2 = req.body.password2;


    let errors = [];
    //
    // if (!name || !email || !password || !password2) {
    //     errors.push({msg: "Please enter all fields"});
    // }
    // if (password && password.length < 6) {
    //     errors.push({msg: "Password must be at least 6 characters"});
    // }
    // if (password != password2) {
    //     errors.push({msg: "Passwords do not match"});
    // }

    if (errors.length > 0) {
        res.render("register", {
            errors,
            name,
            email,
            password,
            password2,
            title: "Register",
            layout: "Layout",
        });
    } else {
        User.findOne({ email: email }).then((user) => {
            if (user) {
                errors.push({ msg: "Email already exists" });
                res.render("register", {
                    errors,
                    name,
                    email,
                    password,
                    password2,
                    title: "Register",
                    layout: "Layout",
                });
            } else {
                const directory = "/images/";
                const newUser = new User({
                    name,
                    email,
                    password,
                    avatar: `./public/uploads/${req.file}`
                });
                const filePath = path.join(__dirname, "../public/uploads/");
                fs.rename(filePath + req.file.filename, req.file.fieldname + '-' + newUser._id + path.extname(req.file.originalname), (error) => {
                    if (error) {
                        return console.log(`Error: ${error}`);
                    }
                });
                newUser.avatar = 'public/uploads/' + req.file.fieldname + '-' + newUser._id + path.extname(req.file.originalname);
                console.log(newUser);
                bcrypt.genSalt(10, (err, salt) => {
                    bcrypt.hash(newUser.password, salt, (err, hash) => {
                        if (err) throw err;
                        newUser.password = hash;
                        newUser
                            .save()
                            .then((user) => {
                                req.flash(
                                    "success_msg",
                                    "You are now registered and can log in"
                                );
                                res.redirect("/users/login");
                            })
                            .catch((err) => console.log(err));
                    });
                });
            }
        });
    }
});

// Login
router.post("/login", (req, res, next) => {
    passport.authenticate("local", {
        successRedirect: "/dashboard",
        failureRedirect: "/users/login",
        failureFlash: true,
    })(req, res, next);
});

// Logout
router.get("/logout", (req, res) => {
    req.logout();
    req.flash("success_msg", "You are logged out");
    res.redirect("/users/login");
});

module.exports = router;

Он без проблем сохранит ваш файл (если ваша конфигурация каталога и имени файла была в порядке).

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...