Step by step guide on uploading files using Vue.js and Express.js

Hello there, I am new to Vuejs and Express and I'm looking to practice my skills.

Currently, I am attempting to build a User Profile with an image upload feature using Vuejs and ExpressJs but unfortunately, none of the files or text are uploading as expected.

Here is a snippet from 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 additional input fields present...

Below is the script section containing functions for the form handling:

<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
  }
}}}

Next 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'
    })}}

Followed by my Model/Profile.js file content:

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 would appreciate any assistance anyone can provide on this matter!

Lastly, here is an excerpt from 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)

}

Answer №1

Here are a couple of key observations:

  1. Make sure to utilize multer as a middleware function

upload.single('file') is a function that should be passed as middleware in your Express routes. Implement 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);

You can then remove the upload code from your post function:

module.exports.post = async (req, res) => {
  // Access the uploaded file through req.file with Multer
  const file = req.file;

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

    // Refactored to use async/await instead of promises for better code organization
    const result = await profile.save();
    return res.status(201).json({ message: "File uploaded successfully!" });
  } catch (error) {
    console.log(error)
    return res.status(500).send({ error: 'An Error occurred while processing' });
  }
}
  1. Check if the name of the file input matches between backend and frontend

You have set up multer to expect a file input named files: upload.single('files'), but in the frontend you are referring to it as file (singular):

formData.append('file', this.files)
. This discrepancy may lead to an unexpected field error by multer. Ensure that these names match exactly.

For tips on handling file uploads in Node.js, check out this informative guide on Parsing Requests in Node.js.

Similar questions

If you have not found the answer to your question or you are interested in this topic, then look at other similar questions below or use the search

Is it possible to generate grid options dynamically for various tables within AngularJS using ui-grid?

I have developed a service for ui-grid table functionality. Currently, I am able to use this service on a single page but now I want to extend its usage to multiple pages, each with different table data. How can I pass grid options and JSON data for multip ...

Guide to activating the timer specifically on select pages with jQuery Mobile

I've developed a quiz application using jQuery Mobile and I am working on implementing a timer feature. The timer should run from 0 seconds up to 1 hour but only when the user is viewing specific pages, specifically the question pages. The timer is di ...

Icon Searchbar Feature in Ionic 2

I am currently working with Ionic2 and have integrated the ion-searchbar component into my project: https://i.sstatic.net/CqmF4.png Question Would it be possible to customize the search icon? The default icon is a magnifying glass, but I would like to r ...

Creating a line break in a Vue.js confirmation dialog is a helpful feature that can be achieved with a

Is there a way to add a new line after the confirmation dialog question and insert a note below it? this.$dialog.confirm("Create Group","Would you like to create group "+ this.groupName +"?<br/>(NOTE: Selected project or empl ...

Error in Node Redis-OM: the function generateId of this[#schema] is not recognized

Hey everyone, I'm currently facing an issue with saving an entity into a Redis repository. The driver is connected correctly, the schema and repo are set up as expected. However, when I attempt to save the entity, I encounter the following exception: ...

Troubleshooting focus loss in React input fields within a Datatable component implemented in a

I noticed an issue with my Datatable where the input field loses focus whenever I type a character and define the component inside another component. Surprisingly, when I directly place the component in the datatable, it works perfectly fine. I understand ...

Using a nested loop in Javascript to fetch JSON data

My goal is to display Categories and their corresponding subcategories in a specific order. However, my current method of using loops within loops is not producing the desired outcome: Category(Mobile) Category(Laptop) Subcategory(Iphone4) Subcategory(Iph ...

Long Polling results in the call stack size being exceeded to the maximum limit

I am working on a long polling function that needs to be triggered at a specific time, and then continue as long as the gallery has the updating class. The gallery is represented by $("... "). function pollGallery(gallery){ if (gallery.hasClass("upda ...

Express routes are malfunctioning

I have a situation with two different routes: /emails and /eamils/:id: function createRouter() { let router = express.Router(); router.route('/emails/:id').get((req, res) => { console.log('Route for get /emails/id'); }); ...

Having trouble with the full-screen feature not functioning properly?

I am currently in the process of creating a custom video player and I need to include a full-screen button. However, when I click on it, the video does not expand to fill up the entire screen. I am using javascript, css3, and html5 for this project. Any as ...

Using Function Call to Generate Components in React

Being tired of repeatedly defining states to render Components based on conditions, I often find myself just wanting to display notifications or alerts. My current dilemma is figuring out how to render a component by invoking a function from within that co ...

Even after trying to hide the legend in a Radar Chart using the configuration option `legend: {display: false}` in chart.js, the legend

Having trouble removing legend from Radar Chart in chart.js even when using legend: {display : false}. The code is being utilized and then displayed with HTML/JS. Here is the provided code snippet: var options5 = { type: 'radar', data: { ...

Handlebars does not support loading data into variables using Express

My NodeJS/Express application utilizes Handlebars for templates, and everything works smoothly except when attempting to display data retrieved from an Express API. The data is successfully fetched and can be viewed in the Chrome debugger. In the problem ...

When I click on the md-select element, a superfluous "overflow-y: scroll;" gets added to the <body> of my webpage

Typically, I have the following styles on my body: element.style { -webkit-app-region: drag; } However, when I interact with a md-select element (you can observe this behavior on the provided link), additional styles are applied. element.style { -w ...

Tips on adding a watermark to multi-page PDFs using an image as the watermark

I am currently working on embedding a watermark onto every page of a PDF file using the image-watermark library. So far, I have successfully added a text watermark to files with only one page but now I am exploring ways to extend this functionality for mul ...

In order to design a v-btn-toggle with vertically aligned buttons, rather than horizontally

I'm currently in the process of developing a quiz using VueJS and Vuetify. My challenge lies in organizing the answer options vertically for the user to select. I attempted to utilize the v-btn-toggle component, but encountered an issue where the butt ...

Steps for deploying a Sucrase-powered API on Heroku

By using Sucrase, I am able to avoid the CommonJS import syntax. I have successfully installed the sucrase dependency and configured Nodemon to register sucrase after Node runs each file. This is my Nodemon config: { "execMap": { "js& ...

Encountering a Material UI error: Incorrect hook usage when combining create-react-library with MUI

After transitioning from Material Ui v3 to v4 on a create-react-library project, I encountered an issue. This particular project serves as a dependency for other projects in order to share components. However, when attempting to display a material-ui compo ...

Once the if condition is implemented, the functionality of the toggle button ceases to operate

Take a look at this demo link: http://jsbin.com/labuxuziraya/1/edit I encountered an issue where the button stops working after adding an if condition. I suspect there are some minor bugs in the code, but my level of experience is not enough to pinpoint t ...

Deleting a file and value in JavaScript

Can you help me figure out how to remove the value of q when the .close class is clicked? Here's my code: $(document).on('click', '.close', function () { $(this).parents('p').remove(); }) $('#Q1DocPath'). ...