0

i am trying to send data to server with Form-Data and axios but it sends undefined values

for detecting that i tried to log all values in server and log formdata in client but server logged undefined values and client logged empty object here is my code

Client:

 handleFormSubmission(e) {
    e.preventDefault();

    var Data = new FormData();    

    Data.append('image', this.fileRef.current.files[0])
    Data.append('name', this.state.name);
    Data.append('time', this.state.time);
    Data.append('portion', this.state.portion);
    Data.append('ingredients', JSON.stringify(this.state.ingredients));
    Data.append('method', this.state.method);
    Data.append('level', this.state.level);
    Data.append('tags', JSON.stringify(this.state.tagsToSend));
      axios.post('/api/post-recipe', Data, {

     headers: {
        'Content-Type': 'multipart/form-data'
     }
   }).then(res => res.data)
     .then(data =>{
      console.log(data.dish)
 })
 .catch(err => {
    if(err.response){
        if(err.response.data.redirect === true){
            window.location.replace(err.response.data.location)
        }
        if(err.response.data.message){
        alert(err.response.data.message)
        }
    }
 })
}

And Server:

 //multer part
 const storage = multer.diskStorage({

 destination: (req, file, callback) => {
 const userPath = path.join(imgStoragePath, req.userId);
 fs.mkdir(
  userPath,
  () => callback(null, userPath)
 )
 },

filename: (req, file, callback) => {
const filenameParts = file.originalname.split('.');
const ext = filenameParts.pop();
const basename = filenameParts.join('.');
const additionalPath = Date.now() + '' + uuid() + '' + 
Math.floor(Math.random() * (2000 - 500)) + 500;
callback(null, basename + '-' + additionalPath + '.' + ext);
}

})

const upload = multer({
storage,
limits: '1mb',
})

//route handling (i have validation in comments because there are some bugs too and i am concentrated on this problem)

 router.post('/', upload.single('image'), async (req, res) => {
 try {

const {
  name,
  time,
  portion,
  ingredients,
  method,
  level,
  tags
} = req.body
const { filename } = req.file;
 /* if (!req.file) {
  return res.status(409).send({
    message: 'გთხოვთ აირჩიოთ მინიმუმ 1 ფოტო'
  })
}



if (name.trim().length < 1) {
  return res.status(409).send({
    message: 'მიუთითეთ კერძის სახელი'
  })
}

if (time.trim().length < 1) {
  return res.status(409)({
    message: 'მიუთითეთ მომზადების დრო'
  })
}

if (!numberToTest.test(time)) {
  return res.status(409).send({
    message: 'დრო ჩაწერეთ ციფრების საშუალებით'
  })
}

if (portion.trim().length < 1) {
  return res.status(409).send({
    message: 'მიუთითეთ პორციის რაოდენობა'
  })
}

if (!numberToTest.test(portion)) {
  return res.status(409).send({
    message: 'პორცია ჩაწერეთ ციფრების საშუალებით'
  })
}

JSON.parse(ingredients).map(({
  ingredient,
  quantity
}) => {
  if (ingredient.trim().length < 1 || quantity.trim().length < 1) {
    return res.status(409).send({
      message: 'მიუთითეთ ინგრედიენტები სრულად'
    })
  }
})

if (method.trim().length < 20) {
  return res.status(409).send({
    message: '"მომზადების მეთოდი"-ს ველში უნდა იყოს მინიმუმ 20 ასო'
  })
}

if (!level == 'მარტივი' || level == 'საშუალო' || level == 'რთული') {
  return res.status(409).send({
    message: 'მიუთითეთ კერძის მომზადების სირთულე'
  })
}

if (JSON.parse(tags).length < 1) {
  return res.status(409).send({
    message: 'მიუთითეთ მინიმუმ 1 მონიშვნა (თეგი)'
  })
}

/*fs.readFile('../tags.json', 'utf8', function (err, content) {
  if (err) {
    return res.status(500).send({
      message: err.message
    })
  }

  const decodedContent = JSON.parse(content)

  if (!decodedContent.tags.includes(JSON.parse(tags))) {
    return res.status(409).send({
      message: 'მიუთითეთ ჩვენს მიერ შემოთავაზებული მონიშვნები (თეგები)'
    })
  }

})*/

 /*   var duplicateTagsGuard = Object.create(null);

for (var co = 0; co < tags.length; co++) {
  let val = tags[co];

  if (val in duplicateTagsGuard) {
    return res.status(409).send({
      message: 'ნუ გამოიყენებთ ერთ მონიშვნას (თაგს) რამდენჯერმე'
    })
  }

  duplicateTagsGuard[val] = true

}
*/

const user = await User.findById(req.userId, '-password -_id -email -loginAttmepts -lockUntil').lean();

const dish = await Dish.create({
  author: user.username,
  name: name,
  time: time,
  portion: portion,
  ingredients: JSON.parse(ingredients),
  method: method,
  level: level,
  tags: JSON.parse(tags),
  createdAt: 'Date- ' + new Date().toLocaleDateString() + ' Time- ' + new Date().toLocaleTimeString()
})

console.log('დიში ' + dish.toObject())


return res.status(200).send({
  dish: JSON.stringify(dish)
})




} catch (error) {
return res.status(500).send({
  message: error.message
  })
 }
})

and log is:

name undefined time undefined portion undefined ingredients undefined method undefined level undefined tags undefined

what is problem? how can i solve it

ilia1
  • 111
  • 3
  • 13
  • Can you try removing the content type header? – i.brod Apr 14 '19 at 11:45
  • of course, 1 min – ilia1 Apr 14 '19 at 11:51
  • nope, it did not work – ilia1 Apr 14 '19 at 12:09
  • before you send the formData , put a console.log to see that those values are defined, maybe the "problem" is on the React side – i.brod Apr 14 '19 at 12:12
  • instead of sending Data i send just `name` variable and it logged in server side – ilia1 Apr 14 '19 at 12:17
  • so you found the problem..? – i.brod Apr 14 '19 at 12:20
  • no i did not. when i am sending `Data` it sends undefined values but when i send `name` variable it logs name, so only thing i get is that problem is in formData – ilia1 Apr 14 '19 at 12:21
  • It's possible that there is a binding problem of "this". Do you make sure the "this" is bound to the React component class? – i.brod Apr 14 '19 at 12:25
  • yes, problem is not that – ilia1 Apr 14 '19 at 12:50
  • do you got any idea? – ilia1 Apr 14 '19 at 12:57
  • can you edit the code, so it shows the entire function from which the ajax is sent? all of it – i.brod Apr 14 '19 at 12:58
  • ajax? i am using axios – ilia1 Apr 14 '19 at 13:06
  • there is nothing more but i still edited – ilia1 Apr 14 '19 at 13:16
  • I dont know :-( – i.brod Apr 14 '19 at 13:46
  • also there is one factor too. when i posted the code here it logged undefined but before that in my server side i was saving that form data in database and it was saving and giving me data that i saved so like if i send data name: 'blah' portion: '1' and etc. it was saving that so in that case server was getting data and this is so confusing – ilia1 Apr 14 '19 at 14:06
  • if you wish i can post that code too – ilia1 Apr 14 '19 at 14:09
  • Seems that maybe you have some logical problem with your React state..because you're saying that sometimes it works, and sometimes it doesn't. I would place a debugger statement in the code, and use the dev-tools step by step to see what's going on. And yes, post whatever code you have – i.brod Apr 14 '19 at 14:10
  • i am really confused, i deleted multer part from my code and it did not work i added it back and it sent data to server i don't know what is happening so i will edit and post full backend code – ilia1 Apr 14 '19 at 14:26
  • by the way when my jwt token expires and i try to send data to server it gives me error ERR_CONNECTION_ABORTED or ERR_CONNECTION_RESET and when i delete file to send it redirects me sign in page (it must do it) – ilia1 Apr 14 '19 at 14:34
  • I see that this data is handled in a route "/". But in your front end, you're sending it to /api/post-recipe. Are you sure you're using the correct function...? – i.brod Apr 14 '19 at 15:08
  • yeah that is correct because i am using `router.use('/api/post-recipe', require('postrecipe.js'))` – ilia1 Apr 14 '19 at 15:23

1 Answers1

1

upload.single('image') may filter out the request body since its not an image content-type, but from the comments it appears the issue may be elsewhere.

Checking around it looks like append seems to be for adding binary entities vs set for form fields - see axios post request to send form data

Catalyst
  • 3,143
  • 16
  • 20
  • i changed append to set and it gave me error :net::ERR_CONNECTION_ABORTED – ilia1 Apr 14 '19 at 15:35
  • @ilia1 is the webserver crashing / aborting the connection? – Catalyst Apr 14 '19 at 15:55
  • no but before i tried this, connection errors occur when i sent request after my jwt token expired – ilia1 Apr 14 '19 at 16:29
  • @ilia1 one thing I do sometimes to debug exactly what is happening is run this in the node.js repl; `new net.Server((s) => {s.on('data', d => process.stdout.write(d));} ).listen(3000)`. Point the UI at "localhost:3000" for the request and it will write out the raw request. I'm suggesting this because I'm not sure what is being sent to the server exactly. If you can edit your post to include the raw HTTP output we may be able to help more. – Catalyst Apr 15 '19 at 15:41