how to send image name in database using multer and express - javascript

When I'm trying to upload a photo with multer and express, everything is OK. But I'm not able to send the image name in mongoose database.
The images are uploaded successfully in the upload directory. I got the imageUrl in the body, but I'm not able to update the image name in mongoose database. However the other details are updated successfully.
Check the image below:
//file upload using multer
var storage = multer.diskStorage({
destination: function (req, file, callback) {
callback(null, './uploads');
},
filename: function (req, file, callback) {
if (!file.originalname.match(/\.(jpg|png|JPEG)$/)) {
var err = new Error();
err.code = 'filetype';
return callback(err);
} else {
callback(null, Date.now() + file.originalname);
}
}
});
var upload = multer({
storage: storage,
limits: {
fileSize: 1000000
}
}).single('userImage');
app.patch('/updateProfile', authenticate, (req, res) => {
upload(req, res, function(err) {
var body = _.pick(req.body, ['name', 'email', 'mobile', 'imageUrl']);
User.findOneAndUpdate({
_id: req.user._id
}, {
$set: body
}, {
new: true
}).then((user) => {
if (!req.file) {
return res.send({
success: false,
msg: 'No file selected'
})
}
if (!user) {
res.status(404).send({
success: false,
msg: 'user not found'
})
} else {
body.imageUrl = req.file.filename;
console.log(body)
res.send({
sucess: true,
msg: 'update sucessfully',
user
})
}
}).catch((err) => {
res.send({
success: false,
msg: 'something wrong',
error: err
});
});
if (err) {
if (err.code === 'LIMIT_FILE_SIZE') {
return res.send({
success: false,
msg: 'limit file size 1MB '
})
} else if (err.code === 'filetype') {
return res.send({
success: false,
msg: 'Must be valid file extension only jpg or png'
})
} else {
return res.send({
success: false,
msg: 'something went wrong'
})
}
}
});
});

var storage = multer.diskStorage({
    destination: function (req, file, callback) {
        callback(null, './images/post');
    },
    filename: function (req, file, callback) {
        if (!file.originalname.match(/\.(jpg|png|JPEG)$/)) {
            var err = new Error();
            err.code = 'filetype';
            return callback(err);
        } else {
            callback(null, Date.now() + file.originalname);
        }
    }
});
var upload = multer({ storage: storage, limits: { fileSize: 1000000 } }).single('imageUrl');
router.post('/posts',authenticate, (req, res) => {
    upload(req, res, function (err) {
        if (err) {
            if (err.code === 'LIMIT_FILE_SIZE') {
                return res.send({ success: false, msg: 'limit file size 1MB ' })
            } else if (err.code === 'filetype') {
                return res.send({ success: false, msg: 'Must be valid file extension only jpg or png' })
            } else {
                return res.send({ success: false, msg: 'something went wrong' })
            }
        } else {
            if (!req.file) {
                return res.send({ success: false, msg: 'No file selected' })
            }
            var post = new Post({
                heading: req.body.heading,
                body: req.body.body,
                imageUrl: req.file.filename,
                creator:req.user.id,
            });
            post.save().then((result) => {
                res.send({ post: result, sucess: true, msg: 'Post created' });
            }).catch((err) => {
                res.send({ sucess: false, msg: 'post not created', error: err })
            });
        }
    });
});

Related

nodejs multer edit a uploaded file with mongodb

i have a website where you can upload files. but i want that you can edit them too. that means the user can press edit en put a new file in and it changes the file on the database. with normal text you can do findByIdAndUpdate. but with a async function youcan. so my question is how can i do this.
here is my code for uploaden
var storage = multer.diskStorage({
destination: (req, file, cb) => {
cb(null, "uploads");
},
filename: (req, file, cb) => {
cb(null, file.fieldname + "-" + Date.now() + ".png");
},
});
var upload = multer({ storage: storage });
router.use(flash())
router.get("/create", (req, res) => {
res.render("uploadPicture", {
items: items,
user: req.auth,
title: "Upload",
});
});
router.get("/", (req, res) => {
image.find({}, (err, items) => {
if (err) {
console.log(err);
res.status(500).send("An error occurred", err);
} else {
res.render("uploadPicture", {
errMsg: req.flash('image'),
items: items,
user: req.auth,
title: "pictures",
});
}
});
});
router.post("/upload", upload.single("image"), async (req, res, next) => {
//const userid = await user.findById({_id : userid});
//console.log(userid);'
const { folder } = sanitize(req.body);
var obj = {
name: req.body.name,
userId: req.auth.userId,
folder: folder,
img: {
data: fs.readFileSync(
path.join(__dirname, "../uploads/" + req.file.filename )
),
contentType: "image/png",
},
};
image.create(obj, (err, items) => {
if (err) {
console.log("Test")
console.log(err);
req.flash('image', 'Image failed to upload!')
res.redirect("/picture")
} else {
console.log(obj);
items.save();
req.flash('image', 'Image succesfully uploaded!')
res.redirect("/picture")
}
});
});
module.exports = router;
and here is what it tried myself but didnt work because i get the error :
TypeError: Cannot read property 'findByIdAndUpdate' of undefined
router.post("/edit/:id", upload.single("image"), async(req, res ) =>{
const id = req.params.id;
console.log(req.params.id)
const { folder } = sanitize(req.body);
var obj = {
name: req.body.name,
userId: req.auth.userId,
folder: folder,
};
if(req.body.image == ""){
console.log("nothing here")
image.findByIdAndUpdate(id, {name: req.body.name,folder: folder,}, function(err, docs){
if (err) {
console.log(err);
req.flash('image', 'Image failed to upload!')
res.redirect("/picture")
} else {
console.log(obj);
req.flash('image', 'Image succesfully uploaded!')
res.redirect("/picture")
}
})
}else{
var image = {
img: {
data: fs.readFileSync(
path.join(__dirname, "../uploads/" + req.file.filename )
),
contentType: "image/png",
},
}
image.findByIdAndUpdate(id, {name: req.body.name,folder: folder,image: image}, function(err, docs){
if (err) {
console.log(err);
req.flash('image', 'Image failed to upload!')
res.redirect("/picture")
} else {
console.log(obj);
req.flash('image', 'Image succesfully uploaded!')
res.redirect("/picture")
}
})
}
})
this last part is a bit messy but i was trying some stuff
i came with a solution if anyone has to do this later
router.post("/edit/:id", upload.single("image"), async (req, res, next) => {
const id = req.params.id;
const { folder } = sanitize(req.body);
if(req.file == null){
console.log("text")
try{
const res = await image.findOneAndUpdate({_id:id}, {name: req.body.name,folder: folder})
console.log(res.name + " " + res.folder + " " + res._id);
}
catch(err){
console.log(err);
}
req.flash('imageView', 'ImageText succesfully to upload!');
res.redirect("/view/" + req.params.id);
}else{
console.log("edit picture")
try{
const res = await image.findOneAndUpdate({_id:id}, {name: req.body.name,folder: folder, img: {data: fs.readFileSync(
path.join(__dirname, "../uploads/" + req.file.filename )
),
contentType: "image/png",
}, })
console.log(res.name + " " + res.folder + " " + res._id);
}
catch(err){
req.flash('imageView', 'Image and text failed to upload!')
res.redirect("/view/" + req.params.id)
console.log(err);
}
req.flash('imageView', 'ImageText succesfully upload!');
res.redirect("/view/" + req.params.id);
}
})
this is how i did it

Node.js passport authentication ignores controller function

If passport returns the user { status: 200 }:
passport.js
...
return done(null, rows[0], { status: 200 });
...
I want the controller 'controllerLogin.login' to be called:
routs/index.js
const express = require('express');
const passport = require('passport');
const passportConf = require('../passport');
const controllerLogin = require('../controllers/login');
...
router.route('/v1/login')
.post( function(req, res, next) {
passport.authenticate('local-login', function (err, user, context = {}) {
if (err) {
console.log(err);
}
if (context.status === 429) {
return res.status(429).send({ status: 429, success: false })
}
if (context.status === 401){
return res.status(401).send({ status: 401, success: false })
}
next();
//return;
})(req, res, next);
}, controllerLogin.login );
But I can't reach the controller 'controllerLogin.login'. What am I missing and how to execute 'controllerLogin.login'?
The below was working, but I need the upper version.
const passLogin = passport.authenticate('local-login', { session: false, failWithError: true });
router.route('/v1/login')
.post( passLogin, function(err, req, res, next) {
return res.status(401).send({ status: 401, success: false })
}, controllerLogin.login );
Edit: What works ...
router.route('/v1/login')
.post( function(req, res, next) {
passport.authenticate('local-login', { session: false, failWithError: false }, function (err, user, context = {}) {
if (err) {
console.log(err);
}
if (context.statusCode === 429) {
return res.status(429).send({ status: 429, success: false, message: { name: 'Rate Limit Error' } })
}
if (context.statusCode === 401){
return res.status(401).send({ status: 401, success: false, message: { name: 'Authentication Error' } })
}
// this works getting user information
console.log('user:');
console.log(user);
next();
})(req, res, next);
}, /*controllerLogin.login*/ (req, res) => { res.status(200).json({just: 'testing'})} );
controller/login.js
module.exports = {
login: async (req, res, next) => {
// Can't access user information via 'req.user' anymore
console.log('req.user:');
console.log(req.user);
/* .. How to access user information here? .. */
res.status(200).json({just: 'testing'})
}
}
It sounds like controllerLogin.login wants req.user, but that is not being set. So try doing that manually in the callback you pass in to passport's authenticate function.
router.route('/v1/login')
.post( function(req, res, next) {
passport.authenticate('local-login', { session: false, failWithError: false }, function (err, user, context = {}) {
if (err) {
console.log(err);
return next(err); // might want to add this line to handle errors?
}
if (context.statusCode === 429) {
return res.status(429).send({ status: 429, success: false, message: { name: 'Rate Limit Error' } })
}
if (context.statusCode === 401){
return res.status(401).send({ status: 401, success: false, message: { name: 'Authentication Error' } })
}
if(!user) {
// might want to handle this separately? user not found?
//return next('User not found');
}
// this works getting user information
console.log('user:');
console.log(user);
req.user = user;
next(); // this moves us on to controllerLogin.login
})(req, res, next);
}, controllerLogin.login);
Then in controller/login
module.exports = {
login: (req, res) => {
// remove user logging once this works, don't want to log sensitive info (!)
console.log('req.user in controller/login:')
console.log(req.user)
// user logic here
res.status(200).json({status: 200, success: true})
}
}
It's worth taking a look at passportjs docs under the "Custom Callback" section. That example doesn't pass along to another function as you are doing, but it can help to see another approach.

passport-jwt returns unauthorized when I go to /admin page on my web app

I am trying to get the user logged in using passport and jwt token. I manage to generate jwt token successfully but when I go to /admin page by typing in the browser I am getting the unauthorized message. I have read all the answer here but they aren't helping me out.
My passport.js file
try {
passport.use('signin', new LocalStrategy(
function(username, password, done) {
Users.findOne({username: username}, (err, user) => {
if (err) { return(err)}
if(!user) { return done(null, false, { message: 'Incorrect username.' })}
if (!checkUser(password, user.password)) { return done(null, false, { message: 'Incorrect username.' }); }
return done(null, user);
});
}
))
} catch (error) {
return done(error);
}
passport.use(new JWTstrategy({
secretOrKey: config.get('jwt.tokenKey'),
jwtFromRequest: ExtractJWT.fromAuthHeaderAsBearerToken()
}, async(token, done) => {
try {
return done(null, token.user);
} catch (err){
done(err);
}
}))
My login-controller file: -
router.post('/', (req, res) => {
passport.authenticate('signin', {session:false}, async(err,user,info) => {
try {
if (err || !user) {
console.log(err);
}
req.login(user, {session:false}, err => {
if (err) res.send(err);
const body = { username: user.username};
const token = jwt.sign( {user:body}, config.get('jwt.tokenKey'));
res.json({ success: true,
token: 'Bearer ' + token });
});
} catch (error) {
return next(error);
}
})(req, res);
})
My admin page file: -
router.get('/', passport.authenticate('jwt', { session: false }), function (req,res) {
res.render('./../views/admin/admin.pug');
})

View is not change after render .pug file from express

I have some problem that the html view is not change after render the pug file,after getting the server response.
The code is following
app.set('view engine', 'pug');
app.set("views", require('path').join(__dirname, "views"));
app.post('/login', function(req, res, next) {
console.log(req.body);
checkExistanceOfuser(req.body.username, req.body.password, function(err, flag, data) {
console.log(err);
if (err) {
res.send({
err: 'SOME_DATABASE_ERROR'
})
} else {
if (flag) {
req.session.user = data;
/*res.send({
success: true,
message: 'Login Success'
})*/
res.render('welcome', { name: data.name });
} else {
/*res.send({
success: false,
message: 'Invalid Credentials'
});*/
res.render('login', { error: 'Invalid Credentials' });
}
}
})
But i check in network section from browser.The API response (preview) is fine.
when you are calling /login route it's a post call and probably you are using ajax post call for doing so.
Now when you are calling the /login route its rendering the pug file
but its not actually effecting the browser DOM. So what you need to do is this
create a new route like this
app.get('/login-success', function(req, res, next) {
if (req.session && req.session.user) {
res.render('welcome', { name: req.session.user.name });
} else {
res.redirect('/');
}
});
and modify the login function like this
app.post('/login', function(req, res, next) {
console.log(req.body);
checkExistanceOfuser(req.body.username, req.body.password, function(err, flag, data) {
console.log(err);
if (err) {
res.send({
err: 'SOME_DATABASE_ERROR'
})
} else {
if (flag) {
req.session.user = data;
res.send({
success: true,
message: 'Login Success'
});
} else {
res.send({
success: false,
message: 'Invalid Credentials'
});
}
}
})
});
in ajax call use this
function login(){
$.post("http://localhost:8000/login",
{
username:document.getElementById("name").value,
password:document.getElementById("password").value,
},
function(data, status){
if(data.success){
window.location = "http://localhost:8000/login-success"
}
});
}
You're rendering views/login, but you've already specified that the view folder is views. Just render login.

MULTER-S3: TypeError: Cannot convert object to primitive valu…diate [as _immediateCallback]

I'm building a MEAN stack app using Multer-s3 to upload images to my database. However when I call the upload function I get this error:
POST http://localhost:3000/api/upload/single 500 (Internal Server Error)
TypeError: Cannot convert object to primitive valu…diate [as _immediateCallback](timers.js:354:15)↵", status: 500, config: Object, statusText: "Internal Server Error"
In my server side app.js
// MULTER
var s3config = require('./config/s3');
var upload = multer({
storage: s3({
dirname: s3config.dirname,
bucket: s3config.bucket,
secretAccessKey: process.env.AWS_ACCESS_SECRET,
accessKeyId: process.env.AWS_ACCESS_KEY,
region: s3config.region,
contentType: function(req, file, next) {
next(null, file.mimetype);
},
filename: function(req, file, next) {
var ext = '.' + file.originalname.split('.').splice(-1)[0];
var filename = uuid.v1() + ext;
next(null, filename);
}
})
});
// UPLOAD SINGLE FILE
app.post('/api/upload/single', upload.single('file'), function(req, res) {
var clothing_1 = {
type: req.body.type,
image: req.file.key
};
console.log('req.body =' + req.body);
console.log('req.body.type =' + req.body.type);
console.log('req.file.key =' + req.file.key);
// get the user model User.findOne({ id: req.user._id })
User.findOne({ _id: req.user._id }, {}, { new: true }, function(err, user){
user.clothing.push(clothing_1);
// save this user
user.save(function(err, user){
if(err) return res.status(401).send({ message: 'your error:' + err });
else return res.json({ user: user })
});
});
});
In my Front-end Controller:
self.uploadSingle = function() {
Upload.upload({
url: API + '/upload/single',
data: { file: self.file, type: self.clothingType }
})
.then(function(res) {
self.usersClothing = res.data.user.clothing.map(function(clothing) {
clothing.image = S3_BUCKET + clothing.image;
return clothing;
});
})
.catch(function(err) {
console.error(err);
});
}
This function is executed when I press upload button.
Was simply a matter of server not being able to find the user as req.body gave _id inside _doc.
User.findOne({ _id: req.user._doc._id } fixed the issue

Categories