Новый синтаксис экспресс-валидатора: валидация формы, обработанной мультером

Итак, я создаю небольшое приложение, чтобы научиться использовать 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 все еще пусто

Я работал над ошибками, и решение простое.

  1. Решение Просто замените слово запроса телом, и ошибка будет устранена.

в новой документации используются ключевые слова запроса, но они работают неправильно.

Используйте const { body, validationResult } = require('express-validator') вместо const { query, validationResult } = require('express-validator')

пример: body('email', "неверный адрес электронной почты").isEmail(),

Другие вопросы по тегам