Uploading image with vuejs to Nodejs Server not working - node.js

Sending form data with text content to Nodejs server from vuejs front end but the file is never uploaded to the server. I had been stack for a while now. Here is my detailed front and backend code:
Front End
//Front end VueJS
Upload form component
<template>
<div class="container">
<form v-on:submit.prevent="addMember" method="post">
<div class="row">
<div class="col-sm-10 col-md-10 col-lg-10">
<div class="form-group">
<label>Title<span class="required-field">*</span>:</label>
<input type="text" class="form-control" v-model="member.title" name="title" v-validate="'required|min:10'">
<div class="help-block alert alert-danger" v-show="errors.has('title')">
{{errors.first('title')}}
</div>
</div>
</div>
</div>
<div class="row">
<div class="col-sm-10 col-md-10 col-lg-10">
<div class="form-group">
<label>Full Name<span class="required-field">*</span>:</label>
<input type="text" class="form-control" v-model="member.fullname" name="fullname" v-validate="'required|min:10'">
<div class="help-block alert alert-danger" v-show="errors.has('fullname')">
{{errors.first('fullname')}}
</div>
</div>
</div>
</div>
<div class="row">
<div class="col-sm-10 col-md-10 col-lg-10">
<div class="form-group">
<label>Passport Photo
<input type="file" id="file" ref="photo" v-on:change="handleFileUpload()"/>
</label>
</div>
</div>
</div>
</form>
<div class="row">
<div class="col-sm-10 col-md-10 col-lg-10">
<div class="form-group">
<button class="btn btn-info btn-lg pull-right">Save</button>
</div>
</div>
</div>
</div>
</template>
<script>
export default {
name:'CreateMember',
data(){
return{
member:{},
photo:'',
}
},
},
methods: {
handleFileUpload(){
this.coverimage = this.$refs.photo.files[0]
},
addMember(){
this.$validator.validateAll().then(()=>
{
let formData = new FormData();
formData.append('file', this.photo);
let rawData = this.member
rawData = JSON.stringify(rawData)
formData.append('data',rawData)
this.axios.post('/members',this.member,{
'content-type':'multipart/form-data'
}).then((resp)=>{
console.log(resp.data)
//this.$router.push({name: 'members'})
}).catch((error)=>{
console.log(error)
})
});
}
}
}
</script>
Back End (Nodejs and Express)
**routes/members.js**
var express = require('express');
var router = express.Router();
//Require Controller Modules
var controller = require('../controllers/MembersController');
var auth = require('../middleware/auth');
const path = require('path');
const multer = require('multer');
//Define file storage engine
const storage = multer.diskStorage({
destination:'public/uploads/',
filename: (req,file,cb)=>{
cb(null,file.fieldname+'-'+Date.now()+path.extname(file.originalname));
}
});
//Filter uploaded file and only upload file types of enumerated format
const fileTypeFilter = (req, file, cb)=>{
if(file.mimetype==='image/jpeg'||file.mimetype==='image/jpg'|| file.mimetype==='image/png'){
cb(null, true);
}
else{
cb(new error('Invalid Image Format'), false);
}
}
const upload = multer({storage:storage,
limits:
{
fileSize:1024*1024*1000
},
filefilter:fileTypeFilter
});
//Save new member to the database
router.post('/members', upload.single('photo'),auth,controller.createMember);
Controllers/MembersController.js
var express = require('express');
var router = express.Router();
const fs = require('fs');
const Model = require('../models/index');
const Member = Model.sequelize.import('../models/member');
//createMember Controller Method
exports.createMember = function(req, res, next) {
//Check if the cover image is attached
if(!req.file)
{
return res.status(400).json({message:'Attach Photo!'}); //The request is returning this response, meaning the file is never uploaded. And the file actually is not being uploaded
}
Member.create({
title: req.body.title,
fullname : req.body.fullname,
photo : req.body.req.file.path
}).then(member=>{
res.json(member);
}).catch((error)=>{
return res.json({status:500,error:error});
});
};
Removing file from request the rest of the data is saved into the database as expected
Model
//Models/member.js
'use strict';
module.exports = (sequelize, DataTypes) => {
var Member = sequelize.define('Member', {
fullname: DataTypes.STRING,
photo: DataTypes.STRING
}, {});
Member.associate = function(models) {
// associations can be defined here
};
return Member;
};
What may be doing wrong. The upload directory is empty. please help me out.

Related

cloudinary multiple file upload error nodejs

I am trying to do a multiple file upload using Cloudinary, but for some reason, it only picks the last file I upload and not all 4 of the files, it returns only one file in the array.
Here are the files
Multer.js
const path = require("path");
//setting the storage engine
const storage = multer.diskStorage({
filename: function (req, file, cb) {
cb(
null,
file.fieldname + "-" + Date.now() + path.extname(file.originalname)
);
},
});
// Check File Type
function checkFileType(file, cb) {
// Allowed extension format
const filetypes = /jpeg|jpg|png|pdf/;
// Check the extension format
const extname = filetypes.test(path.extname(file.originalname).toLowerCase());
// Check mime
const mimetype = filetypes.test(file.mimetype);
if (mimetype && extname) {
return cb(null, true);
} else {
req.flash("error", "Invalid File");
cb("ERROR: Please upload a valid filetype");
return res.redirect("back");
}
}
//initialize the file uplaod
const upload = multer({
storage: storage,
//limits file size
fileFilter: function (req, file, cb) {
checkFileType(file, cb);
},
});
module.exports = { upload };
cloudinary.js
const { CLOUDINARY_CLOUD_NAME, CLOUDINARY_API_KEY, CLOUDINARY_API_SECRET } =
process.env;
const cloudinarySetup = async () => {
cloudinary.config({
cloud_name: CLOUDINARY_CLOUD_NAME,
api_key: CLOUDINARY_API_KEY,
api_secret: CLOUDINARY_API_SECRET,
});
};
// cloudinary upload method
const cloudinaryMediaUpload = async (file, folder) => {
await cloudinarySetup();
return new Promise((resolve) => {
cloudinary.uploader.upload(
file,
{
resource_type: "auto",
folder: folder,
},
(err, result) => {
if (err) throw err;
resolve({
url: result.secure_url,
id: result.public_id,
});
}
);
});
};
module.exports = { cloudinaryMediaUpload };
defaultController.js
const { Business } = require("../models/business");
const { cloudinaryMediaUpload } = require(".././config/cloudinary");
module.exports = {
indexGet: (req, res) => {
let pageTitle = "Home";
res.render("default/index", { pageTitle });
},
aboutGet: (req, res) => {
let pageTitle = "About";
res.render("default/about", { pageTitle });
},
contactGet: (req, res) => {
let pageTitle = "Contact";
res.render("default/contact", { pageTitle });
},
registerGet: (req, res) => {
let pageTitle = "Register";
const { businessName, businessAddress, businessPhone } = req.body;
res.render("default/register", {
pageTitle,
businessName,
businessAddress,
businessPhone,
});
},
registerPost: async (req, res) => {
const { businessName, businessAddress, businessPhone, businessCategory } =
req.body;
// console.log(req.body);
console.log(req.files);
let errors = [];
// Checking Required Field
if (
!businessName ||
!businessAddress ||
!businessPhone ||
!businessCategory
) {
errors.push({ msg: "All fields are required" });
}
let validatePhone = validatePhoneNumberSync(businessPhone);
if (!validatePhone.isValid === true) {
errors.push({ msg: "Invalid phone number" });
}
if (errors.length > 0) {
let pageTitle = "Register";
res.render("default/register", {
pageTitle,
businessName,
businessAddress,
businessPhone,
errors,
});
} else {
Business.findOne({ businessName }).then(async (buss) => {
if (buss) {
errors.push({
msg: "A business with this name is already registered",
});
let pageTitle = "Register";
res.render("default/register", {
pageTitle,
businessName,
businessAddress,
businessPhone,
errors,
});
} else {
// uploading files to cloud
const uploader = async (path) => {
const folderName = businessName
.trim()
.toLowerCase()
.replace(/^[^A-Z0-9]+/gi, function (match) {
return arguments[2].toUpperCase();
});
console.log(folderName);
await cloudinaryMediaUpload(path, "folderName");
};
const urls = [];
const files = req.files;
for (const file of files) {
const { path } = file;
const cloudPath = await uploader(path);
urls.push(cloudPath);
}
const newBusiness = new Business({
businessName,
businessAddress,
businessPhone,
businessCategory,
});
newBusiness.save();
req.flash("success_msg", "Business successfully registered");
res.redirect("/");
}
});
}
},
};
register.ejs
<%- include("../partials/default/header") %>
<div class="form_wrapper">
<div class="form_container">
<div class="title_container">
<h2 style="color: #65b54a;">Business Registration</h2>
</div>
<div class="row clearfix">
<div class="">
<%- include ("../partials/messages"); %>
<form action="/register" enctype="multipart/form-data" method="POST">
<div class="row clearfix">
<div class="col_half">
<div class="input_field"> <span><i aria-hidden="true" class="fa fa-user"></i></span>
<input type="text" name="businessName" placeholder="Business Name" required
value="<%= businessName || '' %>" />
</div>
</div>
<div class="col_half">
<div class="input_field"> <span><i aria-hidden="true" class="fa fa-map-marker"></i></span>
<input type="text" name="businessAddress" placeholder="Business Address" required
value="<%= businessAddress || '' %>" />
</div>
</div>
</div>
<div class="row clearfix">
<div class="col_half">
<div class="input_field"> <span><i aria-hidden="true" class="fa fa-phone"></i></span>
<input type="text" name="businessPhone" placeholder="Business Phone Number" required
value="<%= businessPhone || '' %>" />
</div>
</div>
<div class="col_half">
<div class="input_field select_option">
<select name="businessCategory">
<option selected disabled>Business Category</option>
<option>Technology</option>
<option>Agriculture</option>
<option>Fashion</option>
<option>Entertainment</option>
</select>
<div class="select_arrow"></div>
</div>
</div>
</div>
<!-------------------------Files upload section---------------->
<div class="row clearfix">
<div class="col_half">
<div class="input_field d-flex justify-content-around">
<input type="file" name="bussFile" multiple accept=".pdf, .png, .jpg, .jpeg" id="img"
style="display:none;" />
<label for="img" class="btn btn-success"><span class="d-none d-md-inline mr-2"><i aria-hidden="true"
class="fas fa-upload"></i></span>Upload Incorporation Document</label>
</div>
</div>
<div class="col_half">
<div class="input_field d-flex justify-content-around">
<input type="file" name="bussFile" multiple accept=".pdf, .png, .jpg, .jpeg" id="img"
style="display:none;" />
<label for="img" class="btn btn-success"><span class="d-none d-md-inline mr-2"><i aria-hidden="true"
class="fas fa-upload"></i></span>Upload Company's Profile</label>
</div>
</div>
</div>
<div class="row clearfix">
<div class="col_half">
<div class="input_field d-flex justify-content-around">
<input type="file" name="bussFile" multiple accept=".pdf, .png, .jpg, .jpeg" id="img"
style="display:none;" />
<label for="img" class="btn btn-success"><span class="d-none d-md-inline mr-2"><i aria-hidden="true"
class="fas fa-upload"></i></span>Upload Financial Statements</label>
</div>
</div>
<div class="col_half">
<div class="input_field d-flex justify-content-around">
<input type="file" name="bussFile" multiple accept=".pdf, .png, .jpg, .jpeg" id="img"
style="display:none;" />
<label for="img" class="btn btn-success"><span class="d-none d-md-inline mr-2"><i aria-hidden="true"
class="fas fa-upload"></i></span>Upload Investment Pitch Deck</label>
</div>
</div>
</div>
<input class="button" type="submit" value="Register" />
<!-- <button type="submit" class="btn btn-info">
Register
</button> -->
</form>
</div>
</div>
</div>
</div>
<%- include("../partials/default/footer") %>
And this happens to be the array I get back when I submit. Only the last file upload was picked and not all 4 of the uploads
[
{
fieldname: 'bussFile',
originalname: 'tab.png',
encoding: '7bit',
mimetype: 'image/png',
destination: 'C:\\Users\\HP\\AppData\\Local\\Temp',
filename: 'bussFile-1664784129792.png',
path: 'C:\\Users\\HP\\AppData\\Local\\Temp\\bussFile-1664784129792.png',
size: 68329
}
]
When I check out the documentation here -
It looks like only a single "file" is supported at one time.
https://cloudinary.com/documentation/image_upload_api_reference#upload_required_parameters
Details about how to upload more in parallel here:
https://support.cloudinary.com/hc/en-us/articles/202520662-How-can-I-bulk-upload-my-images-#:~:text=Cloudinary's%20upload%20API%20supports%20a,files%20in%20a%20short%20term.

request body empty when send form data to node js rest API

I created an HTML form to store data into MSSQL
This is the form:
<form [formGroup]="insProtocolloForm" (ngSubmit)="sumit()" enctype="multipart/form-data">
<div class="modal-dialog modal-dialog-centered">
<div class="modal-content">
<div class="modal-header">
<h5 class="modal-title" id="newProtInStaticBackdropLabel">Nuovo protocollo in entrata</h5>
<button type="button" class="btn-close" data-bs-dismiss="modal" aria-label="Close"></button>
</div>
<div class="modal-body">
<div class="form-group">
<label for="dataEmissione">Data Emissione</label>
<input formControlName="dataEmissione" id="dataEmissione" name="dataEmissione" type="text" class="form-control" />
</div>
<div class="form-group">
<label for="anno">Anno</label>
<input formControlName="anno" id="anno" name="anno" type="text" class="form-control" />
</div>
<div class="form-group">
<label for="sede">Sede</label>
<input formControlName="sede" id="sede" name="sede" type="text" class="form-control" />
</div>
<div class="form-group">
<label for="entrataUscita">#Entrata Uscita</label>
<input formControlName="entrataUscita" id="entrataUscita" name="entrataUscita" type="text" class="form-control" />
</div>
<div class="form-group">
<label for="fileToUpload">File</label>
<input formControlName="fileToUpload" id="fileToUpload" name="fileToUpload" type="file" class="form-control" (change)="onFilechange($event)" />
</div>
</div>
<div class="modal-footer">
<button type="button" class="btn btn-secondary" data-bs-dismiss="modal">Annulla</button>
<button type="submit" class="btn btn-success">Inserisci</button>
</div>
</div>
</div>
</form>
And this is the component.ts
import { Component, OnInit } from '#angular/core';
import { CrudService } from '../service/crud.service';
import { DatePipe } from '#angular/common'
import { HttpClient } from '#angular/common/http';
import { FormGroup, FormControl, Validators} from '#angular/forms';
#Component({
selector: 'app-header',
templateUrl: './header.component.html',
styleUrls: ['./header.component.css']
})
export class HeaderComponent implements OnInit {
insProtocolloForm = new FormGroup({
dataEmissione: new FormControl('', [Validators.required]),
anno: new FormControl('', [Validators.required]),
sede: new FormControl('', [Validators.required]),
entrataUscita: new FormControl('', [Validators.required]),
fileToUpload: new FormControl('', [Validators.required]),
fileSource: new FormControl('', [Validators.required])
});
constructor(private crudService: CrudService, private http: HttpClient) { }
get f(){
return this.insProtocolloForm.controls;
}
onFilechange(event: any) {
//console.log(event.target.files[0])
if (event.target.files.length > 0) {
const fileToUpload = event.target.files[0];
this.insProtocolloForm.patchValue({
fileSource: fileToUpload
});
}
}
sumit() {
console.log('### INIZIO SUBMIT() ###');
const formData = new FormData();
formData.append('dataEmissione', this.insProtocolloForm.get('dataEmissione')?.value);
formData.append('anno', this.insProtocolloForm.get('anno')?.value);
formData.append('sede', this.insProtocolloForm.get('sede')?.value);
formData.append('entrataUscita', this.insProtocolloForm.get('entrataUscita')?.value);
formData.append('fileToUpload', this.insProtocolloForm.get('fileSource')?.value);
console.log(formData);
if (this.insProtocolloForm.get('fileSource')?.value) {
this.http.post('http://localhost:8090/api/inserisci-protocollo', formData)
.subscribe(res => {
console.log('res: ' + res);
alert('Uploaded Successfully.');
});
} else {
alert("Si prega di scegliere un file da caricare")
}
console.log('### FINE SUBMIT() ###');
}
ngOnInit(): void { }
}
On submit I call the Node JS REST API
const sqlController = require('./controllers/dboperations-sql');
const express = require('express');
const cors = require('cors');
const multer = require('multer');
const storage = multer.memoryStorage()
const upload = multer({ storage: storage })
const app = express();
const router = express.Router();
app.use(express.json());
app.use(express.urlencoded({ extended: true }));
app.use(cors());
app.use('/api', router);
app.use(upload.single());
router.use((request,response,next)=>{
next();
})
//Inserisco un nuovo protocollo -> /inserisci-protocollo
router.route('/inserisci-protocollo').post((request,response)=>{
console.log('### Requested: Insert new Protocol ###');
/*request.on('data', data => {
console.log(data.toString());
});*/
let newProtocollo = request.body;
//console.log(newProtocollo);
sqlController.addProtocollo(newProtocollo).then(result => {
response.status(201).json(result);
})
})
And here is the problem. The request.body is always empty.
But if I enable the "request.on('data', data => {..." code, I see all form fields.
I also tried to send data with postman but I have the same result.
With postman, if I set the "form-data" option, the body is always empty, but if I set the "x-www-form-urlencoded" option I see all data except the file.
Can anyone help me to solve this problem?
I've read a lot of posts about it but haven't been able to find a solution yet.
I'm going crazy
Thank you very much
Adriano
You need to add the content type headers in the request from angular's http client.
const httpOptions = {
headers: new HttpHeaders({
'Content-Type': 'multipart/form-data'
})
};
this.http.post('http://localhost:8090/api/inserisci-protocollo', formData, httpOptions)

ExpressJs File upload Issue

Even on uploading a file with .jpg or .png format it shows
format not allowed, please upload file with '.png','.gif','.jpg'.
I don't know why it is happening. How to solve or fix this issue? I tried to use ways suggested on some other websites to solve this issue but I wasn't able to fix this issue.
routes.js:
const {
con,
sessionStore
} = require('./config/db');
exports.new = function(req, res){
message = '';
if(req.method == "POST"){
const post = req.body;
const username= post.username;
const title= post.title;
const state= post.state;
const category= post.category;
const description= post.description;
if (!req.files)
return res.status(400).send('No files were uploaded.');
const file = req.files.uploaded_image;
var img_name=file.name;
if(file.mimetype == "image/jpeg" ||file.mimetype == "image/png"||file.mimetype == "image/gif" ){
file.mv('public/imgs/uploads/'+file.name, function(err) {
var sql = "INSERT INTO `nt_data`(`username`,`title`,`state`,`category`, `images` ,`description`) VALUES ?";
var query = con.query(sql, [username, title, state, category, img_name, description], function(err) {
if (!err) {
res.redirect('show/' + username);
}
else {
message = "This format is not allowed , please upload file with '.png','.gif','.jpg'";
res.render('new.ejs',{message: message});
}
});
});
}
}
else {
res.render('new');
}
};
exports.show = function(req, res){
let message = '';
var username = req.params.username;
const sql="SELECT * FROM `nt_data` WHERE `username`='"+username+"'";
con.query(sql, function(err, result){
if(result.length <= 0)
message = "show not found!";
res.render('show.ejs',{data:result, message: message});
});
};
part of my new.ejs file
<form action="/" method="POST" role="form" enctype="multipart/form-data" class="was-validated">
<% if (message.length > 0) { %>
<div class="alert alert-success col-sm-12"><%= message %></div>
<% } %>
<div class="input-group mb-3 input-group-lg">
<div class="input-group-prepend">
<span class="input-group-text">Username</span>
</div>
<input type="text" class="form-control" required placeholder="Enter Username" name="username">
<div class="valid-feedback">Valid.</div>
<div class="invalid-feedback">Please fill out this field.</div>
</div>
<div class="input-group mb-3 input-group-lg">
<div class="input-group-prepend">
<span class="input-group-text">Title</span>
</div>
<input type="text" class="form-control" required placeholder="Enter Title" name="title">
<div class="valid-feedback">Valid.</div>
<div class="invalid-feedback">Please fill out this field.</div>
</div>
<div class="custom-file mb-3">
<input type="file" class="custom-file-input" id="customFile" name="uploaded_image">
<label class="custom-file-label" for="uploaded_image">Choose file</label>
</div>
You should use multer for image or file uploading to server. Because you must use buffer to transfer data from user to local or public server and must create session. You can do these using multer easily.
You can check
https://www.npmjs.com/package/multer

Working form with file upload image in expressjs

What is the simple proper way to upload an image with the form?
I want to upload an image with the form. I have tried working it out but I got "unexpected field". I have installed multer and followed a simple tutorial but not working as expected
This is my route
var express = require('express');
const multer = require('multer');
var router = express.Router();
const multerConfig = {
storage: multer.diskStorage({
//setup where the user's file will go
destination: function(req, file, next){
next(null, './public/images');
},
//then give the file a unique name here
filename: function(reg, file, next){
console.log(file);
const ext = file.mimetype.split('/')[1];
next(null, file.fieldname + '-' + Date.now() + '.'+ext)
}
}),
//a means of ensuring only images are uploaded.
fileFilter: function(req, file, next){
if(!file){
next();
}
const image = file.mimetype.startsWith('image/');
if(image){
console.log('photo uploaded');
next(null, true);
}else{
console.log('file not supported');
return next();
}
}
}
var bookControllers = require("../controllers/bookControllers")
//const csrf = require("../app");
/* GET home page.
router.get('/', function(req, res, next) {
res.render('index', { title: 'Express' });
});
*/
router.get('/', bookControllers.index);
router.post('/addbooks', multer(multerConfig).single('photo'), bookControllers.addbooks);
router.get('/addbooks/:id/:book_url', bookControllers.vieweachbook);
//router.get('/addbooks/:id/edit', bookControllers.edit);
router.get("/:id/edit", bookControllers.edit);
router.get('/:id/delete', bookControllers.delete);
router.put("/:id/update", bookControllers.update);
module.exports = router;
This is addbooks in bookControllers.js
exports.addbooks = function (req, res)
{
const schema = Joi.object().keys({
book_name: Joi.string().trim().min(6).max(25).required(),
summaries: Joi.string().trim().required(),
isbn: Joi.number().required(),
categories: Joi.string().trim().required(),
});
Joi.validate(req.body, schema, (err, result) => {
if(err){
console.log(err)
return res.redirect("/");
}
var url = slug(req.body.categories, {lower: true});
var book_url = slug(req.body.book_name, {lower: true});
//I have to get the auth user and add to the field later
var author = "1";
//Perform knex insert into db
knex('book').insert({
book_name: req.body.book_name,
author: author,
summary: req.body.summaries,
isbn: req.body.isbn,
category: req.body.categories,
image: req.body.image,
url: url,
book_url: book_url
}).then(function(result){
console.log(err)
return res.redirect('/');
});
});
}
and this is the form
<div class="col-lg-4">
<div class="card">
<div class="card-header bg-primary"> Add Books </div>
<form id="c_form-h" class="" method="post" action="/addbooks" enctype="multipart/form-data" style="padding: 5px;">
<div class="form-group row">
<label for="addbookname" class="col-6 col-form-label">Book Name</label>
<div class="col-12">
<input type="text" class="form-control" name="book_name" placeholder="Add Book Name" required>
</div>
</div>
<div class="form-group row">
<label for="addsummary" class="col-6 col-form-label">Summary</label>
<div class="col-12">
<textarea class="form-control" name="summaries" placeholder="Write Some Description" rows="3" required>
</textarea>
</div>
</div>
<div class="form-group row">
<label for="addcategory" class="col-9 col-form-label">Select Category</label>
<div class="col-12">
<input type="number" class="form-control" name="isbn" placeholder="ISBN" required>
</div>
</div>
<div class="form-group row">
<label for="addimage" class="col-9 col-form-label">Add Image</label>
<div class="col-12">
<input type="file" class="form-control-file" name="image" required>
</div>
</div>
<div class="form-group row">
<label for="addcategory" class="col-9 col-form-label">Select Category</label>
<div class="col-12">
<select class="form-control" name="categories" required>
<option></option>
<option>Fruits</option>
<option>Intercontinental Foods</option>
<option>3</option>
<option>4</option>
</select>
</div>
</div>
<button type="submit" class="btn btn-primary">Submit</button>
</form>
</div>
</div>
Also, can some also give me a hint on image update? I mean How to change the image
Thanks
In your HTML you have a file name as image
<input type="file" class="form-control-file" name="image" required>
So, You need to mention the same file name on multer as image instead photo
//Replaced photo with image
router.post('/addbooks', multer(multerConfig).single('image'), bookControllers.addbooks);
Reference : Multer - API Documentation
Update Path on Database :
You will get the file information in req.file on your controller, Like
{ fieldname, originalname, encoding, mimetype, destination, filename, path, size }
Depends on your need you can save file information on your database
knex('book').insert({
...
image: req.file.path,
....
}).then(function(result){

Multer is uploading my image locally but not in my database

I Want to upload a image on my blog post and there is an error, image is alredy in the folder but when i see the database there is noimage.png set as default ...
Im using Multer , there is my code :
Addpost.ejs
<% include ./partials/header %>
<form method="POST" action="/posts/add" enctype="multipart/form-data">
<div class="form-group">
<label>Title</label>
<input class="form-control" name="title" type="text">
</div>
<div class="form-group">
<label>Category</label>
<select class="form-control" name="category">
<% categories.forEach(function(category){ %>
<option value="<%= category.title %>"><%= category.title %></option>
<% }) %>
</select>
</div>
<div class="form-group">
<label>Body</label>
<textarea class="form-control" name="body"></textarea>
</div>
<div class="form-group">
<label>Main Image</label>
<input class="form-control" name="file" type="file">
</div>
<div class="form-group">
<label>Author</label>
<select class="form-control" name="author">
<option value="Arsen Cenko">Arsen Cenko</option>
<option value="John Doe">John Doe</option>
</select>
</div>
<input class="btn btn-default" name
="submit" type="submit" value="save">
</form>
<script src="/app.js"></script>
PostSchema :
var mongoose = require("mongoose")
var postSchema = new mongoose.Schema({
title: String,
created: {type: Date, default: Date.now},
category: [
{
type: mongoose.Schema.Types.ObjectId,
ref: "Category"
}
],
body: String,
file: String })
module.exports = mongoose.model("Post", postSchema);
Post.js Route
var express = require("express");
var router = express.Router();
var Post = require("../models/post");
var Category = require("../models/category");
var path = require('path');
var multer = require('multer');
var storage = multer.diskStorage({
destination: function (req, file, cb) {
cb(null, './public/images/uploads/')
},
filename: function (req, file, cb) {
cb(null, Date.now() + path.extname(file.originalname))
} });
var upload = multer({ storage: storage });
router.get("/add", function(req, res) {
Category.find({}, function(err, categories){
if(err){
console.log(err);
} else{
res.render("addpost", {
title: "Add Post",
categories: categories
})
}
})
})
router.post("/add", upload.single('image'), function(req, res){
var title = req.body.title;
var category = req.body.category;
var body = req.body.body;
var author = req.body.author;
if(req.files && req.files.image){
var imageOriginalName = req.files.image.originalname;
var imageName = req.files.image.fieldname;
var imageMime = req.files.image.mimetype;
var imagePath = req.files.image.path;
var imageExt = req.files.image.extension;
var imageSize = req.files.image.size;
} else {
var imageName = "noimage.png";
}
var newPost = {title:title, category:category, body:body, author:author, image:imageName};
Post.create(newPost, function(err, newPost){
if(err){
console.log("Error");
} else{
res.redirect("/");
}
})
})
Thanks :)
Hey according to documentation
https://github.com/expressjs/multer
using upload.single('image') will get your file in "req.file" not in "req.files"
I think this is the reason your if case fails and jumps to else case. You cannot access it like req.file.image.filename you can simply access it via req.file.filename. Since it is already a "single" file. try console logging the req.file to know what you are getting.
update I think mistake is in your html
<input class="form-control" name="file" type="file">
should be
<input class="form-control" name="image" type="file">
the name attribute of the html should be same as the string in upload.single.
So in your case
upload.single('image')
Now you will receive file in req.file.
Hope it helps.

Resources