Новый синтаксис экспресс-валидатора: валидация формы, обработанной мультером
Итак, я создаю небольшое приложение, чтобы научиться использовать express.js. У меня действительно простая форма, отправив одно текстовое поле и файл одновременно. Это передается через FormData, поэтому я использую multer на серверной части для обработки запроса. То, что я хотел бы сделать, это выполнить проверку текстового ввода формы ПЕРЕД выполнением каких-либо действий в отношении файла (т.е. сохранять только в случае успешной проверки, если не отправить какое-либо сообщение об ошибке). Я делал это так
<form id="form" method='POST' enctype='multipart/form-data'>
<input type='file' id='file-upload' name='file-upload' />
<input type='text' id='text-upload' name='text-upload' />
<input type='submit' />
</form>
Бэкэнд: router.js
//somewhere in the router file
import {importedController} from './controllers/importedController';
/* some other routes */
router.post('/upload', importedController.processfunction);
importedController.js
exports.processfunction = (req, res, next) => {
var getFields = multer().any();
getFields(req, res, err => {
if (err) {return next(err);}
req.checkBody('text-upload','must not be empty!').notEmpty();
//do the validation from here
var errors = req.validationErrors();
if (errors) {
//some logic
} else {
//some other stuff
//in both, i can access req.body and req.file to do whatever i want
}
});
}
Однако я заметил, что для экспресс-проверки существует новый синтаксис, поэтому я попытался следовать этому синтаксису и сделать следующее:
router.js
router.post('/upload', [ body('text-input', 'must be not empty').not().isEmpty()], importedController.processfunction);
но затем в моем импортированном элементе ControlController.js проверка не работает вне определенной мной функции функции getFields() (кажется логичным, поскольку запрос еще не обработан). Тем не менее, если я попытаюсь включить его в функцию multer:
importedController.js
exports.processfunction = (req, res, next) => {
var getFields = multer().any();
getFields(req, res, err => {
if (err) {return next(err);}
errors = validationResult(req);
if (!errors.isEmpty()) {
//actually always yields and error...
} else { //stuff}
});
}
Тогда он всегда возвращает ошибку, хотя запись в поле верна. Это как если бы проверка была выполнена по "необработанному" требованию, где req.body пусто. Хотя код работает сейчас, так что спешить некуда, я бы хотел следовать новому синтаксису для более поздних проектов. Любая помощь с благодарностью!
РЕДАКТИРОВАТЬ: решение, которое я нашел благодаря ответу @ gustavohenke ниже
Понял, что вплоть до сути, моя проблема была связана с тем, как работает модуль multer, так как кажется, что он загружает файл до того, как обрабатывает данные формы (что должно быть перед проверкой) - по крайней мере, модуль multer дает вам нет контроля над тем, когда он загружает файл, что не дает вам возможности вызвать другое промежуточное ПО перед его сохранением.
В итоге я использовал ajax на стороне клиента, чтобы сначала отправить только данные формы (сохраняя файл на потом), в multer().any()
промежуточное программное обеспечение, связанное с логикой проверки формы. В зависимости от ответа, полученного при первом обращении к серверу, я затем связываю его с другим ajax, чтобы наконец загрузить файл на другой маршрут, на этот раз используя multer(storage: myStorage).single('myFileInputName')
загрузить файл.
Думая об этом, это решение кажется, пожалуй, лучше, чем то, о чем я думал вначале: оно не только не позволяет сохранить файл в случае неправильного ввода данных, но даже избегает использования какой-либо полосы пропускания для отправки файла (это может быть довольно тяжелым) если ввод неправильный.
2 ответа
Вы правы, когда говорите, что проверка прошла до того, как тело было обработано multer.
В обоих случаях валидаторы запускаются как можно скорее; но обратите внимание на следующие различия:
- В примере, который вы привели для устаревшего API, вы определяете валидации в обратном вызове multer после обработки тела. Поэтому это работает.
- Однако в вашем примере проверки API валидаторы определены до того, как multer сможет выполнить их, поэтому вы всегда будете иметь ошибки -
req.body
все еще пусто
Я работал над ошибками, и решение простое.
- Решение Просто замените слово запроса телом, и ошибка будет устранена.
в новой документации используются ключевые слова запроса, но они работают неправильно.
Используйте const { body, validationResult } = require('express-validator') вместо const { query, validationResult } = require('express-validator')
пример: body('email', "неверный адрес электронной почты").isEmail(),