I followed a tutorial from udemy on node.js, in this section the video shows that the instructor mongodb cmd passes in profileimage, username, email, password and name. but my code only passes username, email, password and name. And it still says user was registered succesfully. I guess the problem is with multer and i read the documentation and tweaked the code to the new updates found with the documentation. Am i doing the upload i.e req.file with the if/else statement well or what could be the problem with file not being uploaded to folder and loggeed out in monogdb cmd. here are my code samples:
users.js
var express = require('express');
var router = express.Router();
var multer = require('multer');
var uploads = multer({dest: './uploads/'});
/*var storage = multer.diskStorage({
destination: function (req, file, cb) {
cb(null, './uploads/');
},
filename: function (req, file, cb) {
var originalname = file.originalname;
var extension = originalname.split(".");
filename = Date.now() + '.' + extension[extension.length-1];
cb(null, filename);
}
}); */
//Require a model page
var User = require('../models/user');
/* GET users listing. */
router.get('/', function(req, res, next) {
res.send('respond with a resource');
});
router.get('/register', function(req, res, next) {
res.render('register', {
'title': 'Register'
});
});
router.get('/login', function(req, res, next) {
res.render('login', {
'title': 'Log In'
});
});
//router.post('/register', multer({storage: storage, dest: './uploads/'}).single('profileimage'), function(req,res){
router.post('/register', uploads.single('profileimage'), function(req,res,next){
//Get Form Value
var name = req.body.name;
var email = req.body.email;
var username = req.body.username;
var password = req.body.password;
var password2 = req.body.password2;
//Check for Image field
if(req.file){
console.log('uploading File...')
console.log(req.file.path)
// File Info
var profileImageOriginalName = req.files.profileimage.originalname;
var profileImageName = req.files.profileimage.name;
var profileImageMime = req.files.profileimage.mimetype;
var profileImagePath = req.files.profileimage.path;
var profileImageExt = req.files.profileimage.extension;
var profileImageSize = req.files.profileimage.size;
} else {
// Set a Default Image
var profileImageName = 'noimage.png';
}
//Form Validation
req.checkBody('name', 'Name Field is required').notEmpty();
req.checkBody('email', 'Email Field is required').notEmpty();
req.checkBody('email', 'Email not valid').isEmail();
req.checkBody('username', 'Username Field is required').notEmpty();
req.checkBody('password', 'Password Field is required').notEmpty();
req.checkBody('password2', 'Passwords do not match').equals(req.body.password);
//Check for Errors
var errors = req.validationErrors();
if(errors){
res.render('register',{
errors: errors,
name: name,
email: email,
username: username,
password: password,
password2: password2
});
} else {
var newUser = new User({
name: name,
email: email,
username: username,
password: password,
profileImage: profileImageName
});
//Create User
User.createUser(newUser, function (err, user) {
if(err) throw err;
console.log(user);
});
//Success Message
req.flash('success', 'You are now registered and may Log in');
res.location('/');
res.redirect('/');
}
});
module.exports = router;
model/user.js
var mongoose = require('mongoose');
//This chooses the database to use for storing data a very important step
mongoose.connect('mongodb://localhost/nodeauth');
var db = mongoose.connection;
//User Schema
var UserSchema = mongoose.Schema({
username: {
type: String,
index: true
},
password: {
type: String
},
email: {
type: String
},
name: {
type: String
},
profileimaage: {
type: String
}
});
var User = module.exports = mongoose.model('User', UserSchema);
module.exports.createUser = function (newUser, callback) {
newUser.save(callback);
}
app.js
var express = require('express');
var path = require('path');
var favicon = require('serve-favicon');
var logger = require('morgan');
var expressValidator = require('express-validator');
var cookieParser = require('cookie-parser');
var session = require('express-session');
var passport = require('passport');
var LocalStrategy = require('passport-local').Strategy;
var bodyParser = require('body-parser');
//var multer = require('multer');
var flash = require('connect-flash');
var mongo = require('mongodb');
var mongoose = require('mongoose');
var db = mongoose.connection;
var routes = require('./routes/index');
var users = require('./routes/users');
var app = express();
// view engine setup
app.set('views', path.join(__dirname, 'views'));
app.set('view engine', 'jade');
//Handle File Uploads
var upload = multer({ dest: './uploads' });
// uncomment after placing your favicon in /public
//app.use(favicon(path.join(__dirname, 'public', 'favicon.ico')));
app.use(logger('dev'));
app.use(bodyParser.json());
app.use(bodyParser.urlencoded({ extended: false }));
//Handle Express Sessions
app.use(session({
secret:'secret',
saveUninitialized: true,
resave: true
}));
//Passport
app.use(passport.initialize());
app.use(passport.session());
// Validator
app.use(expressValidator({
errorFormatter: function(param, msg, value) {
var namespace = param.split('.')
, root = namespace.shift()
, formParam = root;
while(namespace.length) {
formParam += '[' + namespace.shift() + ']';
}
return {
param : formParam,
msg : msg,
value : value
};
}
}));
app.use(cookieParser());
app.use(express.static(path.join(__dirname, 'public')));
app.use(flash());
app.use(function (req, res, next) {
res.locals.messages = require('express-messages')(req, res);
next();
});
app.use('/', routes);
app.use('/users', users);
// catch 404 and forward to error handler
app.use(function(req, res, next) {
var err = new Error('Not Found');
err.status = 404;
next(err);
});
// error handlers
// development error handler
// will print stacktrace
if (app.get('env') === 'development') {
app.use(function(err, req, res, next) {
res.status(err.status || 500);
res.render('error', {
message: err.message,
error: err
});
});
}
// production error handler
// no stacktraces leaked to user
app.use(function(err, req, res, next) {
res.status(err.status || 500);
res.render('error', {
message: err.message,
error: {}
});
});
module.exports = app;
register.jade
extends layout
block content
h1 Register
p Please register using the form below
ul.errors
if errors
each error, i in errors
li.alert.alert-danger #{error.msg}
form(method='post', action='/users/register',endtype='multipart/form-data')
.form-group
label Name
input.form-control(name='name', type='text', placeholder='Enter Name')
.form-group
label Email
input.form-control(name='email', type='email', placeholder='Enter Email')
.form-group
label Username
input.form-control(name='username', type='text', placeholder='Usernamee')
.form-group
label Password
input.form-control(name='password', type='password', placeholder='Enter Password')
.form-group
label Password
input.form-control(name='password2', type='password', placeholder='Confirm Password')
.form-group
label Profile Image
input.form-control(name='profileimage', type='file')
input.btn.btn-default(name='submit', type='submit', values='Register')
This is way too much code for me to be able to track down the problem for you. What exactly is the problem? and can you try to boil it down to a minimum example which shows the problem?
This post method only post text fields in my form, the file field is not always posted for i do not see the uploaded file nor see it logged out in monogdb command line.
here is the post method
var multer = require('multer');
var uploads = multer({dest: './uploads/'});
router.post('/register', uploads.single('profileimage'), function(req,res,next){
//Get Form Value
var name = req.body.name;
var email = req.body.email;
var username = req.body.username;
var password = req.body.password;
var password2 = req.body.password2;
//Check for Image field
if(req.file){
console.log('uploading File...')
console.log(req.file.path)
// File Info
var profileImageOriginalName = req.files.profileimage.originalname;
var profileImageName = req.files.profileimage.name;
var profileImageMime = req.files.profileimage.mimetype;
var profileImagePath = req.files.profileimage.path;
var profileImageExt = req.files.profileimage.extension;
var profileImageSize = req.files.profileimage.size;
} else {
// Set a Default Image
var profileImageName = 'noimage.png';
}
here is my form field in jade template
form(method='post', action='/users/register',endtype='multipart/form-data')
.form-group
label Name
input.form-control(name='name', type='text', placeholder='Enter Name')
.form-group
label Email
input.form-control(name='email', type='email', placeholder='Enter Email')
.form-group
label Username
input.form-control(name='username', type='text', placeholder='Usernamee')
.form-group
label Password
input.form-control(name='password', type='password', placeholder='Enter Password')
.form-group
label Password
input.form-control(name='password2', type='password', placeholder='Confirm Password')
.form-group
label Profile Image
input.form-control(name='profileimage', type='file')
input.btn.btn-default(name='submit', type='submit', values='Register')
I was having issues saving images to a directory using multer...
// dest folder is not forgiving of forward slashes before the directory name
// turns out the forward slash was the problem
export const multerStorage = multer({ dest: 'mobileFolder/' }); <-- works
export const multerStorage = multer({ dest: '/mobileFolder/' }); <-- does not work
also, might want to check out your request payload with ng2-uploader and other similar multi form packages as the may rename your form's name attribute to 'file'
Content-Disposition: form-data;
name="file"; <--- this is set to file instead of my original name="mobileImage" attribute
filename="Screen Shot 2016-11-17 at 9.54.46 AM.png"
Content-Type: image/png
------WebKitFormBoundaryXwFyVedzgrgJbcuM--
// this proves to be a real pain in the royal ass when you require multer to accept single/array from a form name attribute that does not exist
.post(multer({ dest: 'mobileFolder/' }).single('file') <--- will work
.post(multer({ dest: 'mobileFolder/' }).single('mobileImage') <--- will not work
Why - endtype='multipart/form-data'??
must be - enctype='multipart/form-data'
I have similar problem using multer when i use file destination in below format
const upload = multer({dest : 'uploads/'}); <-- it works
but when i use diskstorage it fails
const storage = multer.diskStorage({
destination: function(req, file, cb) {
cb(null, './uploads/');
},
filename: function(req, file, cb) {
cb(null, new Date().toISOString() + file.originalname);
}
});
const upload = multer({storage : storage});
and the error is.
Error: ENOENT: no such file or directory, open 'C:\projects\alecadApi\uploads\2018-07-07T08:30:14.436Z406fe7245f1d7abdaa8ba9431febdf6a.jpg'
Anyone please help me to solve this.
@adityakmr7 does the directory C:\projects\alecadApi\uploads\ exist?
yes it is already created while using
const upload = multer({dest : 'uploads/'});
What happens if you open a Node.js shell and type:
fs.writeFileSync('C:\\projects\\alecadApi\\uploads\\2018-07-07T08:30:14.436Z406fe7245f1d7abdaa8ba9431febdf6a.jpg', 'test')
hy @LinusU thanks for your response.
I think i fixed it i found something on stackoverflow
i did this
in product.js
new Date().toISOString() Behind add replace() change ":"
Windows OS file don't accept ":" named
on youtube is the MAC OS
E.g
new Date().toISOString().replace(/:/g, '-')
@adityakmr7 spot on the issue for me, on win10.
You have on mongoose 'imaage' field. Use upload.single('imaage')
Most helpful comment
hy @LinusU thanks for your response.
I think i fixed it i found something on stackoverflow
i did this
in product.js
new Date().toISOString() Behind add replace() change ":"
Windows OS file don't accept ":" named
on youtube is the MAC OS
E.g
new Date().toISOString().replace(/:/g, '-')