我在上传图片之前尝试验证我的表单,但我的中间件上出现空字符串
const upload = multer({
storage: storage
});
router.post('/upload', formsValidation, upload.fields([{
name: 'images',
maxCount: 20
}, {
name: 'imageMain',
maxCount: 1
}]), function(req, res, next) {
code...
});
这是我的中间件:
function formsValidation (req, res, next) {
console.log(req.body) //getting empty array here
return next();
}
我知道我可以使用 multer 的 fileFilter 但有时我没有任何图像可以上传只是字符串来存储和验证,我试图将 req.body 从 multipart/form-data 解析为字符串然后验证并使用 next( ) 但我得到一个范围错误,我该如何解决这个问题?
这是来自 Multer 的docs:
请注意,req.body 可能尚未完全填充。这取决于 按照客户端将字段和文件传输到服务器的顺序。
这意味着你必须在 multer 中间件之后调用
formsValidation
,以确保所有发布的数据都已完全填充
router.post('/upload', upload.fields([{
name: 'images',
maxCount: 20
}, {
name: 'imageMain',
maxCount: 1
}]), formsValidation, function(req, res, next) {
code...
});
问题
在调用Multer中间件之前(
upload.fields(...)
),请求体还没有开始解析。您在 req
中间件中收到的 Express formValidation()
对象只是 http.IncomingMessage
的实例,它本身是 stream.Readable
的实例,其数据尚未被消费。只有在您调用 Multer upload.fields(...)
中间件(或 Multer 提供的任何其他中间件)后,req
流才会通过 Busboy
(Multer 使用的 multipart/form-data
请求解析器)进行管道传输,然后解析字段和文件并填充(按它们出现的顺序)到req.body
.
解决方案
不幸的是,Multer 不提供处理现场事件的功能,只提供文件。您可以在收到文件之前验证
req.body
中填充的字段(如 this Github issue 中所述),但是:
我不知道有任何其他使用 Multer 的解决方法。这就是为什么我写了
pechkin
来解决这个确切的问题。
pechkin.parseFormData()
返回一个 Promise
,它在所有字段都被解析时解析,and 如果遇到第一个文件(或请求结束)。fields
对象,和一个files
AsyncIterator/AsyncIterable
.这意味着您可以对
fields
对象执行验证,然后才需要处理文件——文件不会被解析、处理、写入内存、保存在任何地方等,直到您决定这样做。
// ESM
import { parseFormData } from 'pechkin';
// CommonJS
const { parseFormData } = require('pechkin');
// ...
app.post(
'/upload',
pechkinFileUpload(/* ...optional configs */),
formsValidation,
(req, res, next) => {
// Process files and/or fields (`req.files`) ...
}
);
function formsValidation (req, res, next) {
console.log(req.body) // No longer empty! Populated with all fields (see note)
return next();
}
// Just a utility function to follow Express' middleware style
function pechkinFileUpload (/* ...optional configs */) {
return async (req, res, next) => {
try {
const { fields, files } = await parseFormData(req, /* ...optional configs */);
req.body = fields;
req.files = files;
return next();
} catch (err) {
return next(err);
}
}
}