0

All the data is being sent to the backend except for the image file. I keep getting req.file is undefined, which prevents data from being stored in the database.

On the server side I have a routes folder with the that handles a new food entry from the user.

const multer = require('multer')

var fs = require('fs')

var storage = multer.diskStorage({
  destination: function(req, file, cb) {
    cb(null, 'uploads')
  },
  filename: function(req, file, cb) {
    cb(null, file.fieldname + '-' + Date.now())
  }
})

var upload = multer({storage: storage})
router.route('/add', upload.single('foodImage')).post((req, res) => {
    var img = fs.readFileSync(req.body.file.path);
    var encode_image = img.toString('base64')
    var finalImg = {
      contentType: req.file.mimetype,
      image: new Buffer(encode_image, 'base64')
    }

    console.log(finalImg);
// remaining code left out 

On the front end I have a form that collects input from user that includes a photo and a text description. This is in a component file.


fileSelectedHandler(e) {
    this.setState({
      selectedFile: e.target.files[0]
    })
  }

onSubmit(e) {
const nutrition = {
            'calories': calories,
            'fat': fat,
            'sugar': sugar,
            'carbs': carbs,
            'cholesterol': cholesterol,
            'protein': protein,
            'photo': result.foods[0].photo.thumb,
            'date': this.state.date,
            'description': this.state.description,
            'food_list': food_list.toString(),
            'foodImage': this.state.selectedFile
        }

        console.log(nutrition);

        axios.post('http://localhost:5000/nutrition/add', nutrition).then(res => console.log(res));
            
        window.location = '/nutrition';

//remaining code hidden


render() {
    return (
<div>
      <h3>Create New Nutrition Log</h3>
      <form onSubmit={this.onSubmit} encType='multipart/form-data'>
        <div className="form-group">
          <label>Upload food image!</label><br></br>
          <input type="file" onChange={this.fileSelectedHandler} name="foodImage"/>
        </div>
        <div className="form-group"> 
          <label>Description: </label>
          <input  type="text"
              required
              className="form-control"
              value={this.state.description}
              onChange={this.onChangeDescription}
              />
        </div>

//remaining code hidden

Andy Chen
  • 85
  • 1
  • 7

1 Answers1

1

. Client Side

To send images from client to the server your request data should have a multipart/form-data structure. You can accomplished that with:

const data = new FormData();

data.append('calories', calories)
data.append('fat', fat)
data.append('sugar', sugar)
data.append('carbs', carbs)
data.append('cholesterol', cholesterol)
data.append('protein', protein)
data.append('photo', result.foods[0].photo.thumb)
data.append('date', this.state.date)
data.append('description', this.state.description)
data.append('food_list', food_list.toString())
data.append('foodImage', this.state.selectedFile)

axios.post('http://localhost:5000/nutrition/add', data)
     .then(res => console.log(res));

Also, this part of the code where you set encType has no use because you are doing a custom post with axios, not directly from form. (You can remove encType).

<form onSubmit={this.onSubmit} encType='multipart/form-data'>

. Server Side

And to get your file from server side:

// BEFORE
// router.route('/add', upload.single('foodImage')).post((req, res) => {

// AFTER
router.route("/add").post(upload.single("foodImage"), (req, res) => {
   // You can get image details (path, fieldname, size, etc) from request.file.
   console.log(req.file);

   // And JSON data, you can get it normally from request.body
   console.log(req.body);

Also take a look at your post path, on server you are setting it as '/add' and on client you are sending the request to 'nutrition/add'

Finally, there is this link that could be useful to you. rest-api-file-ie-images-processing-best-practices

Luis Paulo Pinto
  • 5,578
  • 4
  • 21
  • 35
  • I made those changes but when I console log, req.file is undefined and req.body is empty – Andy Chen Aug 29 '20 at 17:38
  • @AndyChen, i did a change on server side, specifically into router.route, take a look at it. – Luis Paulo Pinto Aug 30 '20 at 01:41
  • After making these changes the image successfully saves in the uploads folder but the console does not log req.body or req.file and nothing saves in the database. – Andy Chen Aug 30 '20 at 04:03
  • I tried the same, but I am only able to get image data but the rest of the form attributes I am not able to retrieve. Can you please suggest – Prasanna Nov 13 '21 at 22:00