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)
}
I notice two things:
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' });
}
}
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.