简体   繁体   中英

Why can't I access req.body with multer?

My app (using vue) allows users to upload files with some info about the data to my node backend. When the user submits the form, this function is triggered:

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
      }

The log statement shows everything that it ought to, and when this request is made, the network tab in the chrome dev tools shows the post data going through, and it has all the values it should:

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

My multer middleware looks like this:

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()
}

The log statement there works, leading me to believe that multer is working.
I can't seem to access this information in back end though. Here I have tried both file and formData as the file name in mult.single('') .

Here is my controller function:

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) => {
                   .............

I've read some other questions, and have made a few adjustments, but I always get an empty object when I log req.body in the controller. Please advise.

EDIT:

Firstly, I remember I had one problem on the frontend (React), by adding headers, which are not needed (somehow by adding formdata headers u **** up everything), here is the example:

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())
        }
    }

Second issue could be on the backend. The thing is, that you can't just simply access file info through the req.body. You need to access it through the 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})

Then pass the photo to where you want to do something with it

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

Basically what I did is I separated regular data with file, and passed them further to combine and conclude the form. Sorry if this won't help, you're very close anyways!

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

Note that req.body might not have been fully populated yet. It depends on the order that the client transmits fields and files to the server.

I don't know why this worked, but everything started functioning as it should when I stopped using multer as an imported middleware, like this:

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()
}

and instead applied it directly to the route function, like this:

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

If anyone knows why that would be the case, please let me know.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM