Image missing with an Error: Cannot set header after they are sent to client
Image missing with an Error: Cannot set header after they are sent to client
我通过分离模型、视图和控制,将我的旧 Demo 项目转换为 MVC 风格,添加了一个新的控制器文件夹。除了存储图像外,所有功能都运行良好。我收到一个错误:Error [ERR_HTTP_HEADERS_SENT]: Cannot set headers after they are sent to the client
我做了一些调试并发现 图像在验证期间存在,但在发送到请求处理程序时不存在存储数据库 object。 Please check this image of debugging output
数据库中还有一个奇怪的错误。 title, body & image path 被插入数据库中两次。我删除了旧的东西并一次又一次地尝试。但仍然注意到,对于使用 '/posts/new' 页面的一次插入:两个相同的 objects 被存储在 mongodb 中。 Image attached from Mongo DB compass
项目流程如下:带有图像的请求 object 从“/posts/new”页面中选取,在验证中间件中进行验证,如果存在标题和图像:将发送到请求处理程序app.post('/posts/store', storePostController);
,它将使用路径存储图像&它将存储一个mongo数据库文档,其中包含数据库中的标题、body和图像路径。
以下代码如下:
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('/');
});
}
- 文件夹结构
Folder structure
也尝试在控制器中使用控制台 req.files 而不是 req.files.image 再次调试后还尝试将验证转换为 function() ,将其导出并在控制器中调用它并使用回调.
错误是,我从控制器文件夹中操作 storePost.js 并且我从 index.js 位于根文件夹中。
path.resolve() 方法需要一个 up 文件夹 & 我们必须在 __dirname[=23 之后传递一个附加参数作为 '..' =]
观察为 path.resolve() 方法提供的参数。以下代码是正确的做法:
image.mv(path.resolve(__dirname, '..', 'public/img', image.name),
async (error) => {
await BlogPost.create({
...req.body,
image: '/img/' + image.name
})
res.redirect('/');
});
一个小错误导致一大堆错误,我无法追查。终于解决了错误。
我通过分离模型、视图和控制,将我的旧 Demo 项目转换为 MVC 风格,添加了一个新的控制器文件夹。除了存储图像外,所有功能都运行良好。我收到一个错误:Error [ERR_HTTP_HEADERS_SENT]: Cannot set headers after they are sent to the client
我做了一些调试并发现 图像在验证期间存在,但在发送到请求处理程序时不存在存储数据库 object。 Please check this image of debugging output
数据库中还有一个奇怪的错误。 title, body & image path 被插入数据库中两次。我删除了旧的东西并一次又一次地尝试。但仍然注意到,对于使用 '/posts/new' 页面的一次插入:两个相同的 objects 被存储在 mongodb 中。 Image attached from Mongo DB compass
项目流程如下:带有图像的请求 object 从“/posts/new”页面中选取,在验证中间件中进行验证,如果存在标题和图像:将发送到请求处理程序app.post('/posts/store', storePostController);
,它将使用路径存储图像&它将存储一个mongo数据库文档,其中包含数据库中的标题、body和图像路径。
以下代码如下: 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('/');
});
}
- 文件夹结构 Folder structure
也尝试在控制器中使用控制台 req.files 而不是 req.files.image 再次调试后还尝试将验证转换为 function() ,将其导出并在控制器中调用它并使用回调.
错误是,我从控制器文件夹中操作 storePost.js 并且我从 index.js 位于根文件夹中。
path.resolve() 方法需要一个 up 文件夹 & 我们必须在 __dirname[=23 之后传递一个附加参数作为 '..' =]
观察为 path.resolve() 方法提供的参数。以下代码是正确的做法:
image.mv(path.resolve(__dirname, '..', 'public/img', image.name),
async (error) => {
await BlogPost.create({
...req.body,
image: '/img/' + image.name
})
res.redirect('/');
});
一个小错误导致一大堆错误,我无法追查。终于解决了错误。