【问题标题】:Image missing with an Error: Cannot set header after they are sent to client图像丢失并出现错误:将标头发送到客户端后无法设置标头
【发布时间】:2022-01-03 07:47:37
【问题描述】:

我通过分离模型、视图和控制将我的旧 Demo 项目转换为 MVC 样式,添加了一个新的控制器文件夹。除了存储图像外,所有功能都运行良好。我收到一个错误:Error [ERR_HTTP_HEADERS_SENT]: Cannot set headers after they are sent to the client

我做了一些调试,发现图像在验证过程中存在,但在发送到请求处理程序时不存在 以存储 db 对象。 Please check this image of debugging output

数据库中还有一个奇怪的错误。 标题、正文和图像路径在 DB 中插入了两次。我删除了旧的东西并一次又一次地尝试。但仍然注意到,对于使用 '/posts/new' 页面的一次插入:两个相同的对象被存储在 mongodb 中。 Image attached from Mongo DB compass

这是项目流程:带有图像的请求对象是从“/posts/new”页面中挑选出来的,在验证中间件中进行验证,如果存在标题和图像:它将被发送到请求处理程序app.post('/posts/store', storePostController);它将使用路径存储图像,它将存储一个 mongo db 文档,其中包含数据库中的标题、正文和图像路径。

以下代码如下: 1) createPost.ejs

<!DOCTYPE html>
<html lang="en">
<!-- Header-->
<%- include('layouts/header'); -%>

    <body>
        <!-- Navigation-->
        <%- include('layouts/navbar'); -%>
            <!-- Page Header-->
            <header class="masthead" style="background-image: url('/assets/img/contact-bg.jpg')">
                <div class="container position-relative px-4 px-lg-5">
                    <div class="row gx-4 gx-lg-5 justify-content-center">
                        <div class="col-md-10 col-lg-8 col-xl-7">
                            <div class="page-heading">
                                <h1>Create New Post</h1>
                            </div>
                        </div>
                    </div>
                </div>
            </header>
            <!-- Main Content-->
            <main class="mb-4">
                <div class="container px-4 px-lg-5">
                    <div class="row gx-4 gx-lg-5 justify-content-center">
                        <div class="col-md-10 col-lg-8 col-xl-7">
                            <div class="my-5">
                                <form action="/posts/store" method="POST" enctype="multipart/form-data">
                                    <div class="form-floating">
                                        <input class="form-control" id="title" name="title" type="text"
                                            placeholder="Enter the title..." />
                                        <label for="title">Title</label>
                                    </div>

                                    <div class="form-floating">
                                        <textarea class="form-control" id="body" name="body" style="height: 12rem"
                                            placeholder="Enter your message here..." style="height: 12rem"></textarea>
                                        <label for="message">Description</label>
                                    </div>

                                    <div class="form-floating">
                                        <input class="form-control" id="image" name="image" type="file"
                                            placeholder="Upload an image" />
                                        <label for="title">Image</label>
                                    </div>

                                    <!-- Submit Button-->
                                    <button id="submitButton" type="submit">Send</button>
                                </form>
                            </div>
                        </div>
                    </div>
                </div>
            </main>
            <!-- Footer-->
            <%- include('layouts/footer'); -%>
                <!-- Scripts-->
                <%- include('layouts/scripts'); -%>
    </body>

</html>

2) index.js

const express = require('express');
const ejs = require('ejs');
const mongoose = require('mongoose'); 
const fileUpload = require('express-fileupload');
//const { resourceUsage } = require('process');

mongoose.connect('mongodb://localhost/my_database', { useNewUrlParser: true }); //Defining a connection

const app = new express();
app.set('view engine', 'ejs');

const validateMiddleware = require('./middleware/validationMiddleware');
const homeController = require('./controllers/home');
const getPostController = require('./controllers/getPost');
const newPostController = require('./controllers/newPost');
const storePostController = require('./controllers/storePost');


app.use(express.static('public'));  
app.use(express.json());
app.use(express.urlencoded());
app.use(fileUpload());
app.use('/posts/store', validateMiddleware);


app.listen(4000, () => {
    console.log('App listening on port 4000');
});


app.get('/', homeController);

app.get('/post/:id', getPostController);

app.get('/posts/new', newPostController);

app.post('/posts/store', storePostController);

3) validationMiddleware.js

module.exports = (req, res, next) => {

    console.log("Executing Validation Middleware")  //Debugging code
    console.log(req.files)                          //Debugging code

    if (req.files == null || req.body.title == "") {

        return res.redirect('/posts/new');
    }
    next();
}

4) storePost.js

const path = require('path');
const BlogPost = require('../models/BlogPost');

module.exports = async (req, res) => {

    let image = req.files.image;

    console.log("Image Name: " + image.name);           //Debugging Code
    console.log("Printing Image : " + req.files.image); //Debugging Code

    image.mv(path.resolve(__dirname, 'public/img', image.name),
        async (error) => {
            await BlogPost.create({
                ...req.body,
                image: '/img/' + image.name
            })
            res.redirect('/');
        });

}
  1. 文件夹结构 Folder structure

【问题讨论】:

    标签: node.js mongodb express model-view-controller file-upload


    【解决方案1】:

    在控制器中尝试控制台 req.files 而不是 req.files.image 一旦再次调试也尝试将验证转换为 function() ,将其导出并在控制器中调用它并使用回调。

    【讨论】:

    • 您的答案可以通过额外的支持信息得到改进。请edit 添加更多详细信息,例如引用或文档,以便其他人可以确认您的答案是正确的。你可以找到更多关于如何写好答案的信息in the help center
    • @aman req.files 和 req.files.image 在这两个地方都给出了相同的响应。在验证器图像存在时,当它到达“请求处理程序”图像时,仅存在其他详细信息..!
    • @aman,验证确实是一个单独的 .js 文件中的函数,我已经导出它并在主控制器中使用它
    • @aman:在我的 index.js 代码上以非 MVC 样式运行绝对正常。只有在 MVC 风格上,它才会给我一个错误。问题不在于验证,问题在于 storePost 功能。我通过切换代码来双重验证它......!
    【解决方案2】:

    错误是,我从控制器文件夹中操作 storePost.js,并且我从根文件夹中的 index.js 复制了代码。 p>

    path.resolve() 方法需要一个向上的文件夹 &我们必须在 __dirname 之后传递一个附加参数作为 '..'

    观察为 path.resolve() 方法提供的参数。下面的代码是正确的方法:

    image.mv(path.resolve(__dirname, '..', 'public/img', image.name),
            async (error) => {
                await BlogPost.create({
                    ...req.body,
                    image: '/img/' + image.name
                })
                res.redirect('/');
            });
    

    一个小错误引发了很多错误,我无法追踪。终于错误解决了。

    【讨论】:

      猜你喜欢
      • 2019-10-20
      • 1970-01-01
      • 2020-07-11
      相关资源
      最近更新 更多