3

Hey please am new to Vuejs and Express...So am trying to practice.

So am trying to create a User Profile with comes with a image Using Vuejs and ExpressJs but none of the file or text is uploading.

This is my CreateProfile.vue file

       <div class="icon-pic">
       <label for="Password">Upload your Logo / Picture</label>
        <input type="file" ref="file" @change="handleFileUpload"/>
      </div>

      <b-input-group class="mb-2">
        <b-form-input
          id="input-small"
          type="text"
          placeholder="Enter your Name"
          required
          :rules="[rules.required]"
          v-model="profile.fullname"
        ></b-form-input>

        <b-form-input
          id="input-small"
          type="text"
          placeholder="Enter your BrandName"
          v-model="profile.brandname"
        ></b-form-input>
      </b-input-group>

Note: There are other inputs...

Below is my script functions for the form

<script>
import ProfileService from '@/services/ProfileService'

export default {
data () {
return {
  profile: {
    fullname: null,
    brandname: null,
    skill1: null,
    skill2: null,
    skill3: null,
    skill4: null,
    socail_handle1: null,
    socail_handle2: null
  },
  file: null,
  error: null,
  rules: {
    required: (value) => !!value || 'Required.'
  }
}},
methods: {
handleFileUpload () {
  const file = this.$refs.file.files[0]
  this.file = file
},
async create () {
  this.error = null
  const formData = new FormData()
  formData.append('file', this.files)
  const areAllFieldsFilledIn = Object.keys(this.profile).every(
    (key) => !!this.profile[key]
  )
  if (!areAllFieldsFilledIn) {
    this.error = 'Please fill in all the required fields.'
    return
  }
  try {
    await ProfileService.post(this.profile, formData)
    this.$router.push({
      name: 'profile'
    })
  } catch (error) {
    this.error = error.response.data.error
  }
}}}

Below is my ProfileController.js file

const {Profile} = require ('../models')
const multer = require ('multer')

const fileFilter = (req, file, cb) => {
const allowedTypes = ["image/jpeg", "image/jpg", "image/png"]
if (!allowedTypes.includes(file.mimetype)){
const err = new Error('Incorrect File');
return cb(err, false)
}
cb(null, true)
}

const upload = multer ({
dest: '../public',
fileFilter,
})

module.exports = {
async post (req, res){
    try {
        upload.single('files')
        const profile = await new Profile({
        profile: this.profile,
        files: req.file
      });
      profile.save().then(result => {
        console.log(result);
        res.status(201).json({
          message: "Done upload!"
        })
      })
    } catch (err) {
        console.log(err)
        res.status(500).send({
        error: 'An Error has occured trying to fetch'
    })}}

Follow by my Model/Profile.js file

module.exports = (sequelize, DataTypes) => {
const Profile = sequelize.define('Profile', {
     files: {
      type: DataTypes.JSON
     },
     fullname: {
       type: DataTypes.STRING,
       allowNull: false
     },
     brandname: DataTypes.STRING,
     skill1: DataTypes.STRING,
     skill2: DataTypes.STRING,
     skill3: DataTypes.STRING,
     skill4: DataTypes.STRING,
     socail_handle1: DataTypes.STRING,
     socail_handle2: DataTypes.STRING
 })
 return Profile 
 }

I hope any one can help me with this please!!!

This is my route.js file

const AuthController = require('./controllers/AuthController')
const AuthControllerPolicy = require('./policies/AuthControllerPolicy')
const ProfileControler = require('./controllers/ProfileController')
const upload = require ('multer')

module.exports = (app) => {
app.post('/register',
    AuthControllerPolicy.register,
    AuthController.register)

app.post('/login',
    AuthController.login)

app.get('/profile',
    ProfileControler.index)
    
app.post('/upload', upload.single('file'),
    ProfileControler.upload)

}

2
  • Perhaps checkout Uppy with Vue.js - I know it's not a proper answer and it depends on if your requirements is creating your own uploader or if you just want simple file uploading in Vue. I am not affiliated with them in any way and it's not really a proper answer but I have used Uppy in the past and it seems to make these things a bit easier. Commented Jun 3, 2021 at 20:39
  • Will check that out 👍 Commented Jun 4, 2021 at 8:26

1 Answer 1

2

I notice two things:

  1. You're not using multer as a middleware function

upload.single('file') returns a function which should be passed as a middleware in your Express routes. You can use it like this in your route.js:

const multer = require('multer');

const upload = multer({
  dest: '../public',
  fileFilter,
});

app.post('/upload', upload.single('file'), ProfileController.post);

Then you can remove the upload code in your post function:

module.exports.post = async (req, res) => {
  // Multer makes your file available at req.file
  const file = req.file;

  try {
    // Don't need to await when creating a new Mongo object
    const profile = new Profile({
      profile: this.profile,
      files: file
    });

    // Refactored this to use async/await instead of promises.
    // Avoid mixing promises with async/await.
    const result = await profile.save();
    return res.status(201).json({ message: "Done upload!" });
  } catch (error) {
    console.log(error)
    return res.status(500).send({ error: 'An Error has occured trying to fetch' });
  }
}
  1. The name of the file input passed to multer doesn't match with frontend

You're configuring multer to look for a file input named files: upload.single('files'), yet in the frontend you're naming it file (singular): formData.append('file', this.files). Usually multer will then throw an unexpected field error. Make sure these two match exactly.

This free guide for Parsing Requests in Node.js will help you handle file uploads in Node.js.

Sign up to request clarification or add additional context in comments.

9 Comments

Thanks so much...I will try that.
So @maximOrlov Since i have added the upload.single('file') to my route. How should my upload method look like? upload.single('files') const profile = await new Profile({profile: this.profile, files: req.file Please!!!
If you post your routes file (where you import ` ProfileController.js`), I can adjust my answer to fit your question.
I've edited my answer to include the new post method. Change your router to use ProfileController.post not ProfileController.upload since the method you're exporting is called post. I've also refactored the post method a little bit, read the comments.
Thanks so much 😊...I will adjust it
|

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.