Express-validator 在 multer 函数后不执行
Express-validator not executing after multer function
我的 express 应用程序中有一个表格,供用户输入一些文本,并上传 1-3 张照片。我正在使用 multer 处理文件上传到我的 S3 存储桶,我正在使用 express-validator
.
验证表单的其余部分
这使我的 POST 路线看起来像:
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 错误,并且它将创建一个新的 Product
if 所有输入都已填写。所以发生的事情是我的 express-validator
没有捕捉到这里的错误 if (!errors.isEmpty()) { // handle errors
,它只是跳过它并直接进入 else { let product = new Product({
。我知道这一点,因为当我将输入留空时,它会抛出缺少模式路径的猫鼬错误。
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
函数,它在我验证文本输入时起作用,所以我知道这种方法确实有效。我只是有一个将它与多重功能结合起来真的很艰难
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', total count of files)
router.post("/list-product",
singleUpload,
- 验证中间件中的其他参数
- 我注意到您没有在表单中添加
businessName
字段,因此这将 return 出错,您可以在表单中添加它或从此处以及模式中删除验证。
[
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
会提供所有body参数和上传的文件对象,
- 只需控制台
req.body
并使用 req.file
将 return 在 S3 中上传的文件的所有详细信息,包括文件名和位置,我建议您使用文件名和位置来自这个对象,我已经控制台了,
- 使用我们从 fileFitler
传递的 req.fileTypeInvalid
处理文件扩展名错误
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");
});
});
请求的合并最终版本:
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=Image error, please make sure your file is JPG or PNG");
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");
});
});
在 uloadController.js
文件中的 fileFilter 中更正,在 req.fileTypeInvalid
和 return 中传递错误,在请求中处理,
const fileFilter = (req, file, cb) => {
if (file.mimetype === "image/jpeg" || file.mimetype === "image/png") {
cb(null, true);
} else {
req.fileTypeInvalid = "Invalid format, only JPG and PNG";
cb(null, false, req.fileTypeInvalid);
}
};
我的 express 应用程序中有一个表格,供用户输入一些文本,并上传 1-3 张照片。我正在使用 multer 处理文件上传到我的 S3 存储桶,我正在使用 express-validator
.
这使我的 POST 路线看起来像:
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 错误,并且它将创建一个新的 Product
if 所有输入都已填写。所以发生的事情是我的 express-validator
没有捕捉到这里的错误 if (!errors.isEmpty()) { // handle errors
,它只是跳过它并直接进入 else { let product = new Product({
。我知道这一点,因为当我将输入留空时,它会抛出缺少模式路径的猫鼬错误。
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
函数,它在我验证文本输入时起作用,所以我知道这种方法确实有效。我只是有一个将它与多重功能结合起来真的很艰难
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', total count of files)
router.post("/list-product",
singleUpload,
- 验证中间件中的其他参数
- 我注意到您没有在表单中添加
businessName
字段,因此这将 return 出错,您可以在表单中添加它或从此处以及模式中删除验证。
[
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
会提供所有body参数和上传的文件对象, - 只需控制台
req.body
并使用req.file
将 return 在 S3 中上传的文件的所有详细信息,包括文件名和位置,我建议您使用文件名和位置来自这个对象,我已经控制台了, - 使用我们从 fileFitler 传递的
req.fileTypeInvalid
处理文件扩展名错误
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");
});
});
请求的合并最终版本:
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=Image error, please make sure your file is JPG or PNG");
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");
});
});
在 uloadController.js
文件中的 fileFilter 中更正,在 req.fileTypeInvalid
和 return 中传递错误,在请求中处理,
const fileFilter = (req, file, cb) => {
if (file.mimetype === "image/jpeg" || file.mimetype === "image/png") {
cb(null, true);
} else {
req.fileTypeInvalid = "Invalid format, only JPG and PNG";
cb(null, false, req.fileTypeInvalid);
}
};