req.body 在 multer 中间件之前的中间件中未定义
我想制作一个应用程序,它从用户那里获取名称和图像,并使用 multer 将其保存到服务器。 问题是我想在保存图像之前验证名称,在 multer 上传中间件之前使用中间件。
这是服务器代码:
const express = require('express');
const app = express();
const ejsMate = require('ejs-mate');
const path = require('path');
const multer = require('multer');
const upload = multer({ dest: 'uploads/' });
app.engine('ejs', ejsMate);
app.set('view engine', 'ejs');
app.set('views', path.join(__dirname, 'views'));
app.use(express.urlencoded({ extended: true }));
app.use(express.json());
app.use(express.static(path.join(__dirname, 'public')));
const validateName = ( req, res, next ) => {
const { name } = req.body;
if ( name.length <= 0 ) return res.send(JSON.stringify({ success: -1 }));
next();
};
app.route('/upload')
.get(( req, res ) => { res.render('index'); })
.post(validateName, upload.single('image_file'), function (req, res) {
console.log(req.file, req.body);
res.send(JSON.stringify({ success: 1 }));
});
app.listen(3000, () => {
console.log("Server started");
});
我使用 fetch api 发送名称和图像:
window.onload = () => {
const submitBtn = document.querySelector("#submit");
const nameInput = document.querySelector('[name="name"');
const imageInput = document.querySelector('[name="image"');
function handleRenderImage() {
console.log( "SUCCESS" );
};
submitBtn.addEventListener('click', async () => {
const formData = new FormData();
const name = nameInput.value;
const image = imageInput.files[0];
formData.append('name', name);
formData.append('image_file', image);
await fetch('/upload', {
method: "POST",
body: formData
})
.then( response => response.json() )
.then( data => {
const { success } = data;
if ( success ) handleRenderImage();
})
.catch(e => { console.error(e); });
});
};
我认为 app.use(express.urlencoded({ Extended: true }));
和 app.use (express.json());
是因为客户端发送的请求应该是 json 编码的。
我如何读取 validateName
中间件中的 req.body ?
I want to make an app that takes a name and an image from user and saves it to the server using multer.
The problem is that i want to validate the name before saving the image, using a middleware before the multer upload middleware.
this is the server code:
const express = require('express');
const app = express();
const ejsMate = require('ejs-mate');
const path = require('path');
const multer = require('multer');
const upload = multer({ dest: 'uploads/' });
app.engine('ejs', ejsMate);
app.set('view engine', 'ejs');
app.set('views', path.join(__dirname, 'views'));
app.use(express.urlencoded({ extended: true }));
app.use(express.json());
app.use(express.static(path.join(__dirname, 'public')));
const validateName = ( req, res, next ) => {
const { name } = req.body;
if ( name.length <= 0 ) return res.send(JSON.stringify({ success: -1 }));
next();
};
app.route('/upload')
.get(( req, res ) => { res.render('index'); })
.post(validateName, upload.single('image_file'), function (req, res) {
console.log(req.file, req.body);
res.send(JSON.stringify({ success: 1 }));
});
app.listen(3000, () => {
console.log("Server started");
});
I am sending the name and image using fetch api:
window.onload = () => {
const submitBtn = document.querySelector("#submit");
const nameInput = document.querySelector('[name="name"');
const imageInput = document.querySelector('[name="image"');
function handleRenderImage() {
console.log( "SUCCESS" );
};
submitBtn.addEventListener('click', async () => {
const formData = new FormData();
const name = nameInput.value;
const image = imageInput.files[0];
formData.append('name', name);
formData.append('image_file', image);
await fetch('/upload', {
method: "POST",
body: formData
})
.then( response => response.json() )
.then( data => {
const { success } = data;
if ( success ) handleRenderImage();
})
.catch(e => { console.error(e); });
});
};
I think the app.use(express.urlencoded({ extended: true }));
and app.use(express.json());
is the reason because the request send from client side should be json encoded.
How can i read the req.body inside validateName
middleware ?
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(1)
首先,如果您从浏览器发送名称和二进制图像,那么您的数据将不会进行 urlencoded 或 JSON。它的内容类型可能为
multipart/form-data
。在某些代码从流中读取正文并为您解析之前,您将无法访问请求正文中的任何数据。如果此内容类型是
multipart/form-data
,那么您必须使用可以读取和解析该类型的中间件(这是multer
可以做的事情)。因此,您要求做的是阅读正文的一部分,解析它,让您查看,然后如果您喜欢,请阅读正文的其余部分。我不知道有任何
multipart/form-data
中间件可以轻松做到这一点。我什至不清楚该名称是否保证在数据中的图像之前到达,因此您可能必须通读整个图像才能获得名称。我建议您做的是解析整个响应,将图像放置在临时位置,然后,如果其余数据看起来合适,您可以将图像放置在其最终位置。如果没有,您可以将其删除。
另一种可能性是将名称从正文中取出并使其成为查询参数(这需要在客户端进行自定义编码)。然后,您可以在读取和解析正文之前查看查询参数。
另一种可能性是将上传分成两部分,第一个请求将为您提供可以独立检查的名称。然后第二个将提供图像。您必须保留一些服务器端状态(可能是快速会话),其名称与上传的图像相关联。我通常不推荐这种方法,因为它有很多边缘情况需要处理,并且尽可能避免请求之间的服务器端状态是一般设计目标。
First off, if you're sending a name and a binary image from a browser, then your data won't be urlencoded or JSON. It will likely have a content-type of
multipart/form-data
.You won't get any access to any data from the body of the request until some code reads the body from the stream and parses it for you. If this content-type is
multipart/form-data
, then you have to use middleware that can read and parse that type (which is somethingmulter
can do).So, what you're kind of asking to do is to read part of the body, parse it, let you look at, then if you like it, read the rest of the body. I'm not aware of any
multipart/form-data
middleware that will do that easily. It's not even clear to me that the name is guaranteed to arrive BEFORE the image in the data so you might have to read through the whole image just to get to the name anyway.What I suggest you do instead, is parse the whole response, put the image in a temporary location and then, if the rest of the data looks appropriate, you can then put the image in its final location. If not, you can delete it.
Another possibility would be take the name out of the body and make it a query parameter (this would require custom coding on the client-side). You can then see the query parameter before you've read and parsed the body.
Another possibility would be to split the upload into two parts, the first request would give you the name which you could check independently. The second would then provide the image. You would have to keep some server-side state (perhaps express-session) that has the name that is to be associated with the uploaded image. I would generally not recommend this approach as it has lots of edge cases to deal with and avoiding server-side state between requests when possible is a general design goal.