Node.js 快速验证程序在multer函数后未执行
我在我的express应用程序中有一个表单,用户可以输入一些文本,还可以上传1-3张照片。我用multer处理文件上传到S3存储桶的过程,用Node.js 快速验证程序在multer函数后未执行,node.js,express,mongoose,multer,express-validator,Node.js,Express,Mongoose,Multer,Express Validator,我在我的express应用程序中有一个表单,用户可以输入一些文本,还可以上传1-3张照片。我用multer处理文件上传到S3存储桶的过程,用expressvalidator验证表单的其余部分 这使我的发布路线看起来像: router.post("/list-product", listLimiter, function (req, res) { singleUpload(req, res, function (err) { // if any multer err
expressvalidator
验证表单的其余部分
这使我的发布路线看起来像:
router.post("/list-product", listLimiter, function (req, res) {
singleUpload(req, res, function (err) {
// if any multer errors, redirect to form
if (err) {
res.redirect(
"list-product" +
"?error=Image error, please make sure your file is JPG or PNG"
);
return;
}
// if no multer errors, validate rest of form
});
});
我在集成express validator
时遇到问题。我已经在这个问题上纠缠了好几天了,我想我快要解决了。我下面的代码将捕获multer错误,如果填写了所有输入,它将创建一个新的产品。所以现在发生的是我的express验证器没有在这里捕获错误if(!errors.isEmpty()){//handle errors
,它只是跳过它,直接转到else{let product=new product({
)。我知道这一点,因为当我将输入留空时,它会抛出一个丢失模式路径的mongoose错误
let upload = require("../controllers/uploadController");
const singleUpload = upload.single("image");
router.post("/list-product", listLimiter, function (req, res, next) {
singleUpload(req, res, function (err) {
// if any multer errors, redirect to form
if (err) {
res.redirect(
"list-product" +
"?error=Image error, please make sure your file is JPG or PNG"
);
return;
}
// if no multer errors, validate rest of form
body("productName")
.trim()
.isLength({ min: 1 })
.withMessage("Please enter the name of your product"),
body("productPrice")
.isNumeric()
.withMessage("Please enter a valid price"),
body("productCategory")
.trim()
.isLength({ min: 1 })
.withMessage("Please select the category of your product"),
body("productDescription")
.trim()
.isLength({ min: 50 })
.withMessage("Minimum 50 characters")
.isLength({ max: 500 })
.withMessage("Maximum 500 characters"),
body("businessName")
.trim()
.isLength({ min: 1 })
.withMessage("Please enter the name of your business"),
body("website")
.trim()
.isURL()
.withMessage("Please enter the URL for your product or business");
check("*").escape();
const errors = validationResult(req);
let errArray = errors.array();
if (!errors.isEmpty()) {
res.render("list", {
form: req.body,
errors: errArray,
msg: "Please check the form for errors",
option: req.body.productCategory,
});
return;
} else {
let product = new Product({
business: req.body.businessName,
productName: req.body.productName,
category: req.body.productCategory,
price: req.body.productPrice,
description: req.body.productDescription,
website: req.body.website,
imageURL:
"https://mybucket.s3-us-west-2.amazonaws.com/" + req.imageName,
imageURL2:
"https://mybucket.s3-us-west-2.amazonaws.com/" + req.imageName,
});
product.save(function (err) {
if (err) {
console.log(err);
return next(err);
}
res.redirect("/list-product");
});
}
});
});
我真的很感激任何帮助或建议,因为我已经被困在这几天了,我觉得自己真的很愚蠢
我将包括最后一块代码,这是我的express validator
函数,当我验证文本输入时,它会工作,所以我知道这种方法确实有效。我只是很难将它与multer函数结合起来
exports.list__post = [
body("productName")
.trim()
.isLength({ min: 1 })
.withMessage("Please enter the name of your product"),
body("productPrice")
.isNumeric()
.withMessage("Please enter a valid price"),
body("productCategory")
.trim()
.isLength({ min: 1 })
.withMessage("Please select the category of your product"),
body("productDescription")
.trim()
.isLength({ min: 50 })
.withMessage("Minimum 50 characters")
.isLength({ max: 500 })
.withMessage("Maximum 500 characters"),
body("businessName")
.trim()
.isLength({ min: 1 })
.withMessage("Please enter the name of your business"),
body("website")
.trim()
.isURL()
.withMessage("Please enter the URL for your product or business"),
check("*").escape(),
(req, res, next) => {
const errors = validationResult(req);
let errArray = errors.array();
if (!errors.isEmpty()) {
console.log(req.body)
res.render("list", {
form: req.body,
errors: errArray,
msg: "Please check the form for errors",
option: req.body.productCategory,
});
return;
} else {
let product = new Product({
business: req.body.businessName,
productName: req.body.productName,
category: req.body.productCategory,
price: req.body.productPrice,
description: req.body.productDescription,
website: req.body.website,
imageURL: "https://mybucket.s3-us-west-2.amazonaws.com/" + req.imageName,
imageURL2:"https://mybucket.s3-us-west-2.amazonaws.com/" + req.imageName,
});
product.save(function (err) {
if (err) {
console.log(err);
return next(err);
}
res.redirect("/list-product");
});
}
},
];
更新:
// uploadController.js
const aws = require("aws-sdk");
const multer = require("multer");
const multerS3 = require("multer-s3");
const crypto = require("crypto");
require("dotenv").config();
// config aws
aws.config.update({
secretAccessKey: process.env.SECRETACCESSKEY,
accessKeyId: process.env.ACCESSKEYID,
region: "us-west-2",
});
const s3 = new aws.S3();
const fileFilter = (req, file, cb) => {
if (file.mimetype === "image/jpeg" || file.mimetype === "image/png") {
cb(null, true);
} else {
cb(new Error("Invalid format, only JPG and PNG"), false);
}
};
const upload = multer({
fileFilter: fileFilter,
limits: { fileSize: 1024 * 1024 },
storage: multerS3({
s3: s3,
bucket: "mybucket",
acl: "public-read",
metadata: function (req, file, cb) {
cb(null, { fieldName: file.fieldname });
},
key: function (req, file, cb) {
req.imageName = crypto.randomBytes(16).toString("hex");
cb(null, req.imageName);
},
}),
});
module.exports = upload;
快速修复:
- 在中间件中调用
singleUpload
,这里您使用upload.single()
上载单个文件,因此您需要从视图文件标记中删除multiple
属性,如果您要上载多个文件,则使用upload.array('field name',文件总数)
- 验证中间件中的其他参数
- 我注意到您没有在表单中添加
businessName
字段,因此这将返回错误,您可以在表单中添加它,也可以在模式中删除验证
- 中间件回调函数,此处
req
将提供上传的所有主体参数和文件对象
- 只要控制台
req.body
并使用req.file
将返回S3中上载的文件的所有详细信息,包括文件名和位置,我建议您使用此对象的文件名和位置,我已经有控制台了
- 使用我们从fileFitler传递的
req.fileTypeInvalid
处理文件扩展名错误
请求的合并最终版本:
router.post(“/list product”,
单上传,
[
body(“productName”).trim().isLength({min:1}).withMessage(“请输入产品名称”),
正文(“productPrice”).isNumeric().withMessage(“请输入有效价格”),
body(“productCategory”).trim().isLength({min:1}).withMessage(“请选择产品的类别”),
body(“productDescription”).trim().isLength({min:50}).withMessage(“最少50个字符”).isLength({max:500}).withMessage(“最多500个字符”),
body(“businessName”).trim().isLength({min:1}).withMessage(“请输入您的企业名称”),
正文(“网站”).trim().isURL().withMessage(“请输入您的产品或业务的URL”),
勾选(“*”).escape()
],
功能(req、res、next){
日志(req.body,req.file);
//文件扩展名错误
如果(请求文件类型无效){
res.redirect(“列出产品“+”?错误=图像错误,请确保您的文件是JPG或PNG”);
返回;
}
常量错误=验证结果(req);
如果(!errors.isEmpty()){
设errArray=errors.array();
让errorsObj={};//单独访问错误
勘误表.地图((项目)=>{
const id=item.param;
删除item.param;
errorsObj[id]=物料;
});
res.render(“列表”{
表格:要求正文,
错误:errorsObj,
msg:“请检查表单是否有错误”,
选项:req.body.productCategory,
});
返回;
}
让产品=新产品({
业务:req.body.businessName,
productName:req.body.productName,
类别:req.body.productCategory,
价格:req.body.productPrice,
描述:req.body.productDescription,
网站:req.body.website,
图像URL:“https://mybucket.s3-us-west-2.amazonaws.com/“+req.imageName,
});
product.save(函数(err){
如果(错误){
控制台日志(err);
返回下一个(错误);
}
res.redirect(“/列出产品”);
});
});
router.post("/list-product",
singleUpload,
[
body("productName").trim().isLength({ min: 1 }).withMessage("Please enter the name of your product"),
body("productPrice").isNumeric().withMessage("Please enter a valid price"),
body("productCategory").trim().isLength({ min: 1 }).withMessage("Please select the category of your product"),
body("productDescription").trim().isLength({ min: 50 }).withMessage("Minimum 50 characters").isLength({ max: 500 }).withMessage("Maximum 500 characters"),
body("businessName").trim().isLength({ min: 1 }).withMessage("Please enter the name of your business"),
body("website").trim().isURL().withMessage("Please enter the URL for your product or business"),
check("*").escape()
],
function (req, res, next) {
console.log(req.body, req.file);
// FILE EXTENSION ERROR
if (req.fileTypeInvalid) {
res.redirect("list-product" + "?error=" + req.fileTypeInvalid);
return;
}
const errors = validationResult(req);
if (!errors.isEmpty()) {
let errArray = errors.array();
let errorsObj = {}; // access errors indiviually
errArray.map((item) => {
const id = item.param;
delete item.param;
errorsObj[id] = item;
});
res.render("list", {
form: req.body,
errors: errorsObj,
msg: "Please check the form for errors",
option: req.body.productCategory,
});
return;
}
let product = new Product({
business: req.body.businessName,
productName: req.body.productName,
category: req.body.productCategory,
price: req.body.productPrice,
description: req.body.productDescription,
website: req.body.website,
imageURL: "https://mybucket.s3-us-west-2.amazonaws.com/" + req.imageName,
});
product.save(function (err) {
if (err) {
console.log(err);
return next(err);
}
res.redirect("/list-product");
});
});