Почему я не могу получить доступ к req.body с помощью multer?

Мое приложение (использующее vue) позволяет пользователям загружать файлы с некоторой информацией о данных в мой серверный узел. Когда пользователь отправляет форму, срабатывает эта функция:

methods: {
      buttonOK () {
        const formData = new FormData()

        formData.append('name', this.detailFirm.name)
        formData.append('description', this.detailFirm.description)
        formData.append('version', this.detailFirm.version)
        formData.append('date', this.detailFirm.date)
        formData.append('file', this.file)

        for (var [key, value] of formData.entries()) {
          console.log(key, value)
        }

        let headers = {
          'Content-Type': 'multipart/form-data',
          'Accept': 'multipart/form-data'
        }

        this.$http.put('/firmware', formData, {headers: headers})
        this.visible = false
      }

Оператор журнала показывает все, что должен, и когда этот запрос сделан, вкладка сети в инструментах chrome dev показывает проходящие данные сообщения и имеет все значения, которые он должен:

name: test
description: test
version: 1
date: 0555-05-05
file: (binary)

Мое промежуточное ПО multer выглядит так:

const multer = require('multer')
const mult = multer({
  dest: '/firmware'
})

module.exports = function (req, res, next) {
  /* --Convert multipart/form-data to useable format within express-- */
  if (req.path === '/firmware') {
    mult.single('file')
    console.log('MULTER MIDDLEWARE')
  }
  next()
}

Оператор журнала там работает, что наводит меня на мысль, что multer работает.
Однако я не могу получить доступ к этой информации в бэкэнде. Здесь я попробовал как file, так и formData в качестве имени файла в mult.single('').

Вот моя функция контроллера:

let firmware = {
    name: req.body.name,
    version: req.body.version,
    description: req.body.description,
    date: req.body.date,
    file: req.body.file
  }
  firmwareRepo.create(firmware, (err, create) => {
                   .............

Я прочитал некоторые другие вопросы и внес несколько корректировок, но я всегда получаю пустой объект, когда я регистрирую req.body в контроллере. Пожалуйста, порекомендуйте.


person Brian    schedule 11.09.2019    source источник


Ответы (3)


РЕДАКТИРОВАТЬ:

Во-первых, я помню, у меня была одна проблема на фронтенде (React), добавлением заголовков, которые не нужны (как-то добавлением заголовков formdata u **** все), вот пример:

data append stuff goes here 

const data = new FormData()

data.append('id', values.id)

......

return async (dispatch) => {
                const respond = await fetch('/api/postdata', {
                method: 'post',
                headers: {
                   //SEE? THIS IS EMPTY
                },
                body: data
            })

            // send form to backend
            dispatch(dataSend())
        }
    }

Вторая проблема может быть на бэкэнде. Дело в том, что вы не можете просто получить доступ к информации о файле через req.body. Вам нужно получить к нему доступ через req.file

  .post('/api/post', (req, res, next)=> {
    const photo = {}
    const newData = {}

    uploadData(req, res, (err) => {
      if(err){
        console.log('error')
      }
      else {
        Object.assign(photo, {file: req.file})
        Object.assign(newData, {newData: req.body})

Затем передайте фотографию туда, где вы хотите что-то с ней сделать.

    const addDataController = new AddDataController(req, res, next, newAdvertData, photo)
    addAdvertController.postAdvert()
  }
})

По сути, я разделил обычные данные с файлом и передал их дальше, чтобы объединить и завершить форму. Извините, если это не поможет, вы все равно очень близки!

person ldruskis    schedule 13.09.2019

https://github.com/expressjs/multer#diskstorage

Обратите внимание, что req.body, возможно, еще не заполнен полностью. Это зависит от порядка, в котором клиент передает поля и файлы на сервер.

person IDIR Samir    schedule 12.09.2019
comment
Я видел, что другие рекомендовали это, и я изменил свой код, чтобы файл добавлялся последним, что решило проблему для других. К сожалению, изменение порядка передачи полей не дало результата. - person Brian; 12.09.2019

Я не знаю, почему это сработало, но все стало работать как надо, когда я перестал использовать multer в качестве импортируемого промежуточного ПО, вот так:

module.exports = function (req, res, next) {
  /* --Convert multipart/form-data to useable format within express-- */
  if (req.path === '/firmware') {
    mult.single('formData')
    console.log('MULTER MIDDLEWARE')
  }
  next()
}

и вместо этого применил его непосредственно к функции маршрута, например:

router.put('/firmware', upload.single('formData'), firmware.create) // doesn't work as standalone middleware

Если кто-нибудь знает, почему это так, пожалуйста, дайте мне знать.

person Brian    schedule 14.09.2019
comment
single - это middleware, который следует использовать в экспресс-маршруте... используя его внутри маршрута, вы просто вызываете single, но его обратный вызов не выполняется. Второй подход является правильным, когда промежуточное ПО выполняет и вызывает next, что является вашей функцией create. Тем не менее, проблема все еще существует... req.body может быть пустым, если изображение не является последней формой, введенной в ваш запрос... это известная проблема из multer, причину которой я понял только сегодня, читая код - person Elmer Dantas; 01.12.2020