我正在使用NodeJS、ejs模板、MongoDB和Express创建一个Web应用程序.我已经创建了多条路由.适用于用户以及其他数据库.我能够成功地获取/REGISTER路径的From POST请求.但无法从/admin/blog/edit/:id路径的正文中获取任何内容.在浏览器和控制台中都没有错误.但是当我拿到身体的时候,我得到了空的物体.

这是我的app.js代码:

if (process.env.NODE_ENV !== 'production') {
    require('dotenv').config()
}



const express = require('express');
const mongoose = require('mongoose');
const ejsLayouts = require('express-ejs-layouts');
const cors = require('cors');
const passport = require('passport');
const flash = require('express-flash');
const session = require('express-session');
const methodOverride = require('method-override');
const webRoutes = require('./routes/webRoutes');
const userRoutes = require('./routes/userRoutes');
const initializePassport = require('./passport-config');

const app = express();

app.use(cors());
app.use(express.json());
app.use(express.urlencoded({ extended: true }));
app.use(express.static(__dirname + '/public'));

app.set('view engine', 'ejs');
app.use(ejsLayouts);

app.use(function(req, res, next) {
    res.locals.currentPage = req.path;
    next();
});


app.use("/", webRoutes);
app.use("/admin", userRoutes);

mongoose.connect('mongodb://127.0.0.1:27017/myDB');

const PORT = process.env.PORT || 3000;
app.listen(PORT, () => {
    console.log(`Server is running on port ${PORT}`);
});

这是我的userRotes.js代码:

if (process.env.NODE_ENV !== 'production') {
    require('dotenv').config()
}


let express = require('express');
const app = express();
const router = express.Router();
const bcrypt = require('bcrypt');
const passport = require('passport');
const flash = require('express-flash');
const session = require('express-session');
const methodOverride = require('method-override');
const fs = require('fs');
const path = require('path');
// const User = require('../models/userModel');
const { Blog, Contact, JobOpening, User } = require('../models/dbModels');

const initializePassport = require('../passport-config')
initializePassport(
    passport, 
    email => users.find(user => user.email === email),
    id => users.find(user => user.id === id)
)



router.use(flash())
router.use(session({
    secret: process.env.SECRET_KEY,
    resave: false,
    saveUninitialized: false
}))
router.use(passport.initialize())
router.use(passport.session())
router.use(methodOverride('_method'))

// Function to get JavaScript filenames
function getAdminJSFiles() {
    const adminJsDir = path.join(__dirname, '..', 'public', 'javascript', 'admin');
    const files = fs.readdirSync(adminJsDir);
    const jsFiles = files.filter(file => file.endsWith('.js'));
    return jsFiles;
}

// Function to get JavaScript filenames
function getAdminCSSFiles() {
    const adminCSSDir = path.join(__dirname, '..', 'public', 'styles', 'admin');
    const files = fs.readdirSync(adminCSSDir);
    const cssFiles = files.filter(file => file.endsWith('.css'));
    return cssFiles;
}

const current_user = true;


// Middleware to set layout for all admin routes
router.use((req, res, next) => {
    if (req.originalUrl.startsWith('/admin/login')) {
        // Exclude layout for login routes
        res.locals.layout = 'layout_login';
        return next();
    }
    res.locals.layout = 'layout_admin'; // Specify the admin layout
    res.locals.jsFiles = getAdminJSFiles(); // Pass the jsFiles variable
    res.locals.cssFiles = getAdminCSSFiles(); // Pass the jsFiles variable
    res.locals.user = { name: "dummyUser", email: 'dummyUser@gmail'}
    next();
});


router.use((req, res, next) => {
    if (req.isAuthenticated()) {
        if (req.originalUrl === '/admin/login') {
            return res.redirect('/admin');
        }
        return next();
    }
    if (req.originalUrl === '/admin/login') {
        return next();
    }
    res.redirect('/admin/login');
});

router.get('/', (req, res) => {
    res.render('./admin/admin_home', { current_user: req.body.email, email: req.body.name, params: req.params });
});

router.get('/register', (req, res) => {
    res.render('./admin/admin_register');
});

router.post('/register', async (req, res) => {
    try {
        const hashedPassword = await bcrypt.hash(req.body.password, 10);
        const newUser = new User({
            email: req.body.email,
            password: hashedPassword,
            role: req.body.role
        });
        await newUser.save();
        res.redirect('/admin/login');
    } catch (error) {
        console.error(error);
        res.redirect('/admin/register');
    }
});

router.get('/login', (req, res) => {
    res.render('./admin/admin_login');
});

router.post('/login', passport.authenticate('local', {
    successRedirect: '/admin',
    failureRedirect: '/admin/login',
    failureFlash: true
}));

router.get('/logout', (req, res, next) => {
    req.logout((err) => {
        if (err) { return next(err); }
        res.redirect('/admin');
    });
});

router.get('/blogs', async (req, res) => {
    try {
      const blogs = await Blog.find();
      res.render('./admin/blogs/blog_home', { blogs });
    } catch (err) {
      console.error(err);
      res.status(500).send('Server Error');
    }
  });


router.get('/blogs/add', async (req, res) => {
    try {
      res.render('./admin/blogs/blog_add', { action: `/admin/blog/add`, blog: {} });
    } catch (err) {
      console.error(err);
      res.status(500).send('Server Error');
    }
}); 

router.get('/blogs/edit/:id', async (req, res) => {
    try {
        const blog = await Blog.findById(req.params.id);
      res.render('./admin/blogs/blog_add', { action: `/admin/blogs/edit/${blog._id}`, blog });
    } catch (err) {
      console.error(err);
      res.status(500).send('Server Error');
    }
});

router.post('/blogs/edit/:id', async (req, res) => {
    try {
        // const { title, seo_name, blog_type, author_name, image, banner_image, publish_date, status, trending, long_description } = req.body;
        // const updatedBlog = {
        //     title,
        //     seo_name,
        //     blog_type,
        //     author_name,
        //     image,
        //     banner_image,
        //     publish_date,
        //     status,
        //     trending,
        //     long_description
        // };
        const userID = req.params.id;
        console.log(userID)
        // await Blog.findByIdAndUpdate(req.params.id, updatedBlog);
        const { title } = req.body;
        console.log('Request Body:', req.body); // Log request body
        console.log('Update Query:', { title }); // Log update query
        // await Blog.findByIdAndUpdate(req.params.id, { title });
        res.redirect('/admin/blogs');

    } catch (err) {
      console.error(err);
      res.status(500).send('Server Error');
    }
});


module.exports = router;

这是我的blog_add.ejs代码:

<div class="content-wrapper">
    <section class="content-header">
        <h1>New</h1>
        <div class="breadcrumb">
            <a class="btn btn-sm btn-info" href="/admin/blogs">Back</a>
        </div>
    </section>
    <section class="content">
        <%- include ('../../partials/admin_form')%>
    </section>
</div>

这是我的admin_form.ejs代码:

<% // include partials/layouts/include_ckeditor.ejs %>
<div class="box box-default">
    <div class="box-header with-border">
        <h3 class="box-title">Form</h3>
        <div class="box-tools pull-right">
            <button class="btn btn-box-tool" data-widget="collapse">
                <i class="fa fa-minus"></i>
            </button>
        </div>
    </div>
    <% // - var f = locals.f; %>
    <h1><%= blog ? 'Edit blog' : 'Add blog' %></h1>
    <form action="<%= action %>" method="post" enctype="multipart/form-data">
        <div class="box-body">
            <div class="row">
                <div class="col-md-6">
                    <div class="form-group">
                        <label>Title</label>
                        <input type="text" name="title" class="form-control" placeholder="Enter Title" value="<%= blog.title || '' %>">
                    </div>
                    <div class="form-group">
                        <label>SEO Name</label>
                        <input type="text" name="seo_name" class="form-control" placeholder="Enter SEO Name" value="">
                    </div>
                    <div class="form-group">
                        <label>Blog Type</label>
                        <select name="blog_type" class="form-control">
                            <option value="BLOG">BLOG</option>
                            <option value="NEWS">NEWS</option>
                        </select>
                    </div>
                    <div class="form-group">
                        <label>Author Name</label>
                        <input type="text" name="author_name" class="form-control" placeholder="Enter Author Name" value="">
                    </div>
                    <div class="form-group">
                        <label>Image</label>
                        <input type="file" name="image" class="form-control">
                        <p style="color:red;">(530px X 429 px)</p>
                    </div>
                    <div class="form-group">
                        <label>Banner Image</label>
                        <input type="file" name="banner_image" class="form-control">
                        <p style="color:red;">(1015px X 452 px)</p>
                    </div>
                    <div class="form-group">
                        <label>Publish Date</label>
                        <input type="text" name="publish_date" class="form-control" placeholder="Enter Publish Date" id="adrt-datepicker" autocomplete="off" value="">
                    </div>
                    <div class="form-group">
                        <label>Status</label>
                        <input type="checkbox" name="status">
                    </div>
                    <div class="form-group">
                        <label>Trending Blog</label>
                        <input type="checkbox" name="trending">
                    </div>
                </div>
                <div class="col-md-6">
                    <div class="form-group">
                        <label>Long Description</label>
                        <textarea name="long_description" class="form-control"></textarea>
                    </div>
                </div>
            </div>
        </div>
        <div class="box-footer">
            <button type="submit" class="btn btn-primary">Submit</button>
        </div>
    </form>
</div>

<script>
    $(document).ready(function(){
        $("#adrt-datepicker").datepicker({
            dateFormat: 'dd/mm/yy',
            maxDate: 0
        });
    });
</script>

问题是,当我try 在/admin/blog/dit/:id路径中提交表单时,没有从该表单获取任何数据.已正确获取id,但未从正文中获取数据.这是正文请求的console.log输出:

id: 65eb8dce672a051114e1a090
Request Body: {}
Update Query: { title: undefined }

推荐答案

问题出在模板中的表单元素:

<form action="<%= action %>" method="post" enctype="multipart/form-data">

属性enctype="multipart/form-data"将表单作为多部分表单数据类型发送,这是上传文件时使用的常见类型,但TE服务器上没有可以处理该格式的中间件(通常的工具是multer),这就是req.body未定义的原因.

如果从表单中删除该属性,表单将以URL编码类型发送,express.urlencoded中间件将处理它,您将获得req.body.

但是,由于您的表单中有两个文件类型为imagebanner_image的字段,您需要发送分块类型请求,并且在服务器端需要设置分块中间件,以及文件上传、目的地、命名等.

因此,如果您不是在上传文件,只需删除enctype="multipart/form-data"个属性:

<form action="<%= action %>" method="post">

但如果您要在服务器上上传文件,您需要设置上传中间件,例如,您可以使用multer,您的代码可能是这样的(您需要确定如何处理文件、将它们保存在哪里、命名等,请参阅链接的文档和示例,这里也使用了这些文档和示例):

// setup upload middleware
const multer  = require('multer');
// setup file destination - you could use in-memory also
const upload = multer({ dest: 'uploads/' });

// you send two file fields, so need to use .fields() method:
const cpUpload = upload.fields([{ name: 'image', maxCount: 1 }, { name: 'banner_image', maxCount: 1 }]);

// add midleware to the route
router.post('/blogs/edit/:id', cpUpload, async (req, res) => {

// handle files, they're in `req.files`
console.log('files', req.files);

Node.js相关问答推荐

如何在JavaScript中使用Mongoose将项推送到MongoDB中的重嵌套数组

如何将我的Redis客户端配置为在禁用群集模式的情况下使用读取副本?

如何修复PostgreSQL和NodeJS/NestJS应用程序之间的日期时间和时区问题?

FiRestore UPDATE方法引发错误:&Quot;错误:13内部:收到代码为1&Quot;的RST_STREAM

如何修复我的 NodeJS SSE 写入函数以在后续调用中更新 HTML?

Solidity 将数据位置从内存更改为存储

node_modules/preact/src/jsx.d.ts:2145:22 - 错误 TS2304:找不到名称SVGSetElement

kubernetes 上的 nextjs 无法启动

获取用户 ID 后,Firebase 函数 onCreate 方法在 Firestore 上不起作用

如何调用同名的两个函数?

来自 child_process.exec 的错误没有这样的设备或地址,管道有帮助.为什么?

如何在 MongoDB collection.find() 上获取回调

npm 不会安装 express 吗?

安全沙箱并执行用户提交的 JavaScript?

无法获取 CSS 文件

按日期时间字段获取最新的 MongoDB 记录

nodejs v10.3.0 的 gulp 任务问题:src\node_contextify.cc:629: Assertion `args[1]->IsString()' failed

Passport 的 req.isAuthenticated 总是返回 false,即使我硬编码 done(null, true)

mongo 可以 upsert 数组数据吗?

node.js 中的意外保留字导入