All 'req.body' values ​are string - Express and multer

Viewed 127

I have a problem getting values ​​other than 'strings', I have a form to upload a photo to cloudinary. When the request data is received, all of them are of type 'string', that is, the values ​​of type object or array, I convert them, for example:

{ name: "name of user" } to [object Object] , true to "true" and ["user1", "user2"] to "user1,user2"

From the cliente side, I have a function that receives the data from the form, and makes the request to the server with axios:

// Request

async function updateUser(formValues) {
  try {
    // Create Form Data
    const formData = new FormData();

    // Form fields
    const fields = Object.keys(formValues);

    for (const field of fields) {
      formData.append(field, formValues[field]);
    }

    const res = await axios({
      method: "PUT",
      url: `mypage/api/updateUser`,
      data: formData,
    });

  } catch (err) {
   //
  }
}

export default updateUser;

On the server side, I have configured multer and express as follows:

'use strict'

const multer = require('multer')
const express, { Router } = require('express')
const app = express()
const router = Router()

// Middlewares
app.use(express.json())
app.use(express.urlencoded({ extended: false }))

// MULTER CONFIG
const diskStorage = multer.diskStorage({
  filename: (_, file, cb) => cb(null, file.originalname)
})

const upload = multer({ storage: diskStorage })

// EXAMPLE
router.post(
  '/api/updateUser',
  upload.single('profilePhoto'),
  function(req, res) {
  /* 
    req.body is equal to {
      name: "User",
      isPremium: true,
      user: { name: "username" },
      favoritesGames: ["World of Warcraft", "Age of Empires"]
    }
  */
  console.log(req.body.user)
  // return "[object Object]"
  
  console.log(req.body.isPremium)
  // return "true"
  
  console.log(req.body.favoritesGames)
  // return "World of Warcraft, Age of Empires"
  
  // I need to get the body data as it arrives 
)

// SET PORT
const port = process.env.PORT

// INIT APP
app.listen(port || 4000, function() {
  console.log('[INFO]', `The server is running on ${process.env.PUBLIC_URL}`)
})

I need the data, as it comes from the client side, the content type is multipart/form-data, it is not application/json, so I think it cannot read data other than 'string'. Any solution?

1 Answers

I found a very good solution for this problem. Practically, from the frontend, you have to send the values ​​wrapped in a JSON.stringify and the problem is solved.

Example:

async function updateUser(values) {
  try {
    // Create Form Data
    const formData = new FormData();

    // Get fields of Form
    const fields = Object.keys(values);
    
    // Types to stringify
    const typesToStringify = ["object", "boolean", "array"]

    for (const field of fields) {
      for (type of typesToStringify) {
        if (typeof formValues[field] === type) {
          formData.append(field, JSON.stringify(values[field]));
        } else {
          formData.append(field, values[field]);
        }
      }       
    }

    // Request to api
  } catch (err) {
    //
  }
}

Related