Как я могу вернуть Multer Error клиенту при использовании Express-Validator?
Обновленная запись: прокрутите страницу вниз для получения обновленной информации.
Оригинальный пост
Мне нужна помощь в этом. Я создаю маршрут, который принимает FormData, проверяет данные файла через Multer (изображения в данном случае), затем проверяет строковые данные с помощью Express-Validator. Я создал рабочий маршрут, который завершает обе проверки, но я не могу понять, как принять какие-либо ошибки от Multer и вернуть их клиенту.
Я установил Multer перед Express-Validator, чтобы req.body мог быть прочитан Express-Validator. При этом я не могу понять, как (или могу ли я вообще) передавать ошибки Малтера для отправки обратно в ответ.
Мой пример ниже должен включать в себя все необходимое для экзамена, но если вам нужна дополнительная информация, пожалуйста, дайте мне знать.
const multer = require('multer')
const {
check,
validationResult
} = require('express-validator/check');
const {
sanitizeBody
} = require('express-validator/filter');
const imageUpload = multer({
dest: 'uploads/',
limits: {
fileSize: 1000000
},
fileFilter: function (req, file, cb) {
let filetypes = /jpeg|jpg/;
let mimetype = filetypes.test(file.mimetype);
let extname = filetypes.test(path.extname(file.originalname).toLowerCase());
if (mimetype && extname) {
return cb(null, true);
}
cb(new Error('Invalid IMAGE Type'))
}
}).fields([{
name: 'cover_image',
maxCount: 1
},
{
name: 'more_images',
maxCount: 2
}
])
const validationChecks = [
check('street', 'Invalid Street Name').matches(/^[a-z0-9 ]+$/i).isLength({
min: 1,
max: 25
}).trim().escape(),
check('city', 'Invalid City Name').matches(/^[a-z ]+$/i).isLength({
min: 1,
max: 15
}).trim().escape()
]
router.post('/addnewproperty', imageUpload, validationChecks,(req, res, next) => {
const errors = validationResult(req);
if (!errors.isEmpty()) {
console.log('text validation FAILED');
return res.status(400).json({
errors: errors.array()
});
}
console.log('validation PASSED');
})
Обновление 6/6/19
Хорошо, я думаю, что нашел решение, хотя и не то, что ожидал.
Используя next()
Я могу использовать Multer в первом обработчике маршрута, где я могу получать и отправлять ошибки Multer в ответе. Если в этом первом обработчике маршрута не возникает ошибок, я могу позвонить next()
, чтобы затем перейти к следующему обработчику маршрута для использования экспресс-валидатора, где я могу проверить и отправить любые ошибки, которые возникают в результате проверки строки.
Код ниже является рабочим примером того, что я описываю. Не уверен, что это приемлемый код, но он работает после небольшого тестирования. Любые мнения или рекомендации по этому поводу приветствуются в комментариях ниже.
// Here's the meat of what I changed.
// The config and variables set in the previous code are the same.
router.post('/addnewproperty',(req, res, next) => {
imageUpload(req,res,(err)=>{
if(err){
console.log(err.message);
return res.status(400).json(err.message)
}
next()
})
})
router.post('/addnewproperty',validationChecks,(req,res)=>{
const errors = validationResult(req);
if (!errors.isEmpty()) {
return res.status(400).json({
errors: errors.array()
});
}
return res.sendStatus(200)
})
Я оставлю этот вопрос открытым, если у кого-то есть лучшее решение для получения того, что я изначально намеревался сделать, кроме кода выше.
4 ответа
Я использовал функцию, которая создает промежуточное ПО Multer, которое можно разместить в любом месте цепочки промежуточного ПО. После этого вы можете использовать req.body без других двоичных полей.
import { Router } from 'express';
import multer from 'multer';
function makeMulterUploadMiddleware(multerUploadFunction) {
return (req, res, next) =>
multerUploadFunction(req, res, err => {
// handle Multer error
if (err && err.name && err.name === 'MulterError') {
return res.status(500).send({
error: err.name,
message: `File upload error: ${err.message}`,
});
}
// handle other errors
if (err) {
return res.status(500).send({
error: 'FILE UPLOAD ERROR',
message: `Something wrong ocurred when trying to upload the file`,
});
}
next();
});
}
const upload = multer({ dest: 'uploads/' });
const multerUploadMiddleware = makeMulterUploadMiddleware(upload.single('image'));
const someRouter = Router();
someRouter.post('', multerUploadMiddleware, (req, res) => {
// now body contains all the fields except the one with the file
res.send(req.body);
});
export { someRouter };
Я обрабатываю req.body с помощью пакета @ hapi / joi npm, но это должно работать с другими валидаторами.
примечание: причина, по которой я не использую err instanceof multer.MulterError
чтобы проверить, является ли ошибка Multer, как описано в документации Multer (https://github.com/expressjs/multer), из-за некоторых ошибок проверки типов в машинописном тексте.
Вы можете получить ошибку, позвонив imageUpload
связующее ПО напрямую, вместо использования его в цепочке промежуточного ПО, как в вашем коде.
Непроверенный фрагмент, но, надеюсь, по крайней мере подтолкнет вас в правильном направлении:
router.post('/addnewproperty', validationChecks, (req, res, next) => {
const errors = validationResult(req);
if (!errors.isEmpty()) {
console.log('text validation FAILED');
return res.status(400).json({
errors: errors.array()
});
}
imageUpload(req, res, (multerErr) => {
if(multerErr){
console.log('Multer validation FAILED');
return res.status(400).json({
errors: [multerErr.message]
});
}else{
console.log('validation PASSED');
}
});
})
Для получения дополнительной информации по этому вопросу приведены официальные документы Multer по обработке ошибок.
Эй, я оставлю тебя с некоторыми фрагментами, которые работали для меня,
Multer без использования файла
const express = require('express'); const multer = require('multer'); const router = express.Router(); const { check, validationResult } = require('express-validator'); var upload = multer(); var tagCreateValidator = [ check('name', 'Name is required') .not() .isEmpty() ]; // @route POST api/tags // @desc Create Tag // @access Public router.post('/', upload.any(), tagCreateValidator, (req, res, next) => { const errors = validationResult(req); if (!errors.isEmpty()) { return res.status(400).json({ errors: errors.array() }); } res.send(req.body); });
это с файлом, хотя я не использую экспресс валидатор прямо сейчас, я обновлю этот ответ, как только это будет сделано
const express = require('express'); const Multer = require('multer'); const gcsMiddlewares = require('../../gcs_middleware'); const router = express.Router(); const multer = Multer({ storage: Multer.storage, limits: { fileSize: 10 * 1024 * 1024 //Maximum file size is 10MB } }); // @route POST api/users // @desc Register user // @access Public router.post( '/', multer.single('avatar'), gcsMiddlewares.sendUploadToGCS, (req, res, next) => { var imageUrl; if (req.file && req.file.gcsUrl) { imageUrl = req.file.gcsUrl; } var responseBody = { file: imageUrl, body: req.body }; res.send(req); } ); module.exports = router;
Я столкнулся с этой проблемой сегодня, за исключением того, что я не использую маршрутизатор. Я хотел иметь возможность вернуть ответ JSON об ошибке, когда проверка типа файла не удалась. Я подумал, что поделюсь своим решением, так как оно может помочь кому-то еще. Мое решение состояло в том, чтобы добавить четвертый параметр к вызову функции app.post() следующим образом:
app.post("/post", fileUpload.single('file'), function(req, res) {
//do some stuff after a successful upload.
},
function(err, req, res, next) {
//File upload encountered an error as returned by multer
res.status(400).json({error: err.message});
})