2

I am trying to upload image to the server and the same time to pass some additional data (in the same post request) using: VueJS 2 (CLI 3), axios, multer, sharp and I have NodeJS with MongoDB in the backend.

Front-end:

<form @submit.prevent="onSubmit" enctype="multipart/form-data">
   <div class="input">
      <label for="name">Name: </label>
        <input
          type="text"
          id="name"
          v-model="name">
    </div>
    <div class="input">
        <label for="last_name">Your last_name: </label>
        <input
              type="text"
              id="last_name"
              v-model="last_name">
     </div>
     <div class="input">
        <label for="permalink">permalink</label>
        <input
              type="text"
              id="permalink"
               v-model="permalink">
     </div>
     <div class="input">
       <label for="price">price</label>
       <input
             type="text"
             id="price"
             v-model="price">
      </div>
      <div class="input">
        <label for="photo">photo</label>
        <input
          style="display: none"
          type="file"
          id="photo"
          @change="onFileSelected"
          ref="fileInput">
        <div @click="$refs.fileInput.click()">Pick file</div>
        </div>
        <div class="submit">
          <md-button type="submit" class="md-primary md-raised">Submit</md-button>
        </div>
</form>

VueJS methods:

import axios from 'axios'
export default {
  data () {
    return {
      name: '',
      last_name: '',
      permalink: '',
      selectedFile: null,
      url: null,
      price: 0,
      second: false
    }
  },
  methods: {
    onFileSelected (event) {
      this.selectedFile = event.target.files[0]
      this.url = URL.createObjectURL(this.selectedFile)
    },
    onUpload () {
      const fd = new FormData()
      fd.append('image', this.selectedFile, this.selectedFile.name)
      axios.post('http...', fd, {
        onUploadProgress: uploadEvent => {
          console.log('Upload Progress ' + Math.round(uploadEvent.loaded / uploadEvent.total * 100) + ' %')
        }
      })
        .then(res => {
          console.log(res)
        })
    },
    onSubmit () {
      const fd = new FormData()          
      fd.append('image', this.selectedFile, this.selectedFile.name)
      fd.append('data', this.name, this.last_name)

      axios.post('http://localhost:7000/api/create-user', fd, {
        onUploadProgress: uploadEvent => {
          console.log('Upload Progress ' + Math.round(uploadEvent.loaded / uploadEvent.total * 100) + ' %')
        }
      })
        .then(res => {
          console.log(res)
          if (res.data === 'ok') {
            this.second = true
          }
        })
        .then(
          setTimeout(function () {
            this.second = false
            this.reset()
          }.bind(this), 2000)
        )
        .catch(error => console.log(error))
    }
  }
}

NodeJS:

controller.postCreateUser = (req, res) => {
  const sharp = require('sharp');
  const fs = require('fs');
  const folderImg = 'backend/uploads/';
  console.log(JSON.stringify(req.body));
  console.log(req.file);
  res.send("ok");    
};

The results of req.file is (which is good):

{ fieldname: 'image',
  originalname: 'musk.jpg',
  encoding: '7bit',
  mimetype: 'image/jpeg',
  destination: 'backend/uploads/original/',
  filename: 'musk-1545470459038.jpg',
  path: 'backend\\uploads\\original\\musk-1545470459038.jpg',
  size: 108787 }

The results of console.log(req.body) is

{"data":""}

The problem is here data has empty string and I don't receive any data. I need having the data to store to my database. How to do that?

If something isn't very clear to you, ask me for more details.

3
  • 1
    I think you problem is on this line, in the front-end: fd.append('data', this.name, this.last_name). You're passing 3 parameters, when only 2 are allowed when sending a String. You can only use 3 when sending a file. You can either concatenate the two Strings: this.name + ' ' + this.last_name, or send both properties separately: fd.append('name', this.name); fd.append('last_name', this.last_name); , or send the data as JSON Commented Dec 22, 2018 at 10:30
  • 1
    that was the problem you can add it as solution if you want with alternative answer as JSON Commented Dec 22, 2018 at 10:37
  • Glad it worked! Commented Dec 22, 2018 at 10:47

1 Answer 1

2

In your onSubmit method, you do this:

const fd = new FormData()
fd.append('image', this.selectedFile, this.selectedFile.name)
fd.append('data', this.name, this.last_name)

But FormData.append() expects these parameters:

  • name - The name of the field whose data is contained in value.
  • value - The field's value. This can be a USVString or Blob (including subclasses such as File).
  • filename Optional - The filename reported to the server (a USVString), when a Blob or File is passed as the second parameter.

The third parameter does not apply on this line: fd.append('data', this.name, this.last_name)

Instead, you can do either of these:

fd.append('data', `${this.name} ${this.last_name}`) // Send a single String

or

// Send both Strings separately
fd.append('name', this.name)
fd.append('last_name', this.last_name)

or

// Send the data as JSON
fd.append('data', JSON.stringify({name: this.name, last_name: this.last_name}))
Sign up to request clarification or add additional context in comments.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.