【问题标题】:Not getting form data in req.body Express/node.js没有在 req.body Express/node.js 中获取表单数据
【发布时间】:2020-11-22 15:08:20
【问题描述】:

我正在尝试通过上传个人资料图片为新用户创建电子注册。但是我的表单数据没有传递给路由。我添加了 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}`));

User.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;

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;

Register.ejs 是表单不向路由传递数据的文件。

<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>

【问题讨论】:

    标签: javascript html node.js express


    【解决方案1】:

    您似乎没有正确使用multer。通常multer 配置是全局设置的,首先是所有API,然后我们将multer 生成的中间件函数传递给请求中包含multipart/form-data 标头的特定API。您必须将multer 的配置移到您的API 之外,然后将upload 作为中间件传递给您的API。同样从您的客户端,您必须正确传递数据。可以在here 中找到关于将 JSON 与带有 FormData 对象的文件一起发送的一个很好的答案。您还可以根据multer 文档从客户端在 FormData 对象中添加文本字段,并在req.body 中将其作为对象接收。只要确保您正确地将数据从客户端传递到服务器。这是带有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;
    

    它会毫无问题地保存你的文件(如果你的目录和文件名配置没问题的话)。

    【讨论】:

    • @Mohsin 您的意思是 multer 正在保存文件,但使用随机名称而不是您在配置中设置的名称?
    • @Mohsin 现在我知道了,我会测试一些东西,如果可行,我会与你分享。
    • 谢谢您,先生。 github.com/mkshuvo/smpms 这是我项目的 GitHub 链接,如果您需要的话。
    • @Mohsin 我已经通过此修复向您的存储库发出了拉取请求,并更新了答案中的代码。我测试了这个解决方案,它可以工作。
    • 实在是太感谢你了。你为我做了很多。该文件被保存在主目录而不是“public/uploads”中。我会尽快调查的。非常感谢,先生。
    猜你喜欢
    • 1970-01-01
    • 2011-11-23
    • 2012-03-07
    • 2013-02-25
    • 2018-11-07
    • 1970-01-01
    • 1970-01-01
    • 2017-12-14
    • 1970-01-01
    相关资源
    最近更新 更多