Sta-Dev
Sta-Dev

Reputation: 305

How to save uploaded image from multer to mongodb in nodejs

I need to save user information from a register form to mongodb. Everything works well except the image file. I am using Multer for uploading images from form to server.

Also to show that image in the profile page once the user logged in.

Below is the code:

signup.ejs:

<form action="/signup" method="post" enctype="multipart/form-data">
    <label for>Profile Picture</label>
    <input type="file" name="image"><br><br>
    <label for>Name</label>              
    <input type="text" name="name"><br><br>
    <label for>Email</label>              
    <input type="email" name="email"><br><br>
    <label for>Password</label>  
</form> 

routes.js:

var multer       = require('multer');

var storage = multer.diskStorage({
   destination: function (req, file, cb) {
   cb(null, './uploads');
},
filename: function (req, file, cb) {
   cb(null, file.originalname);
}
});

var upload = multer({ storage: storage });

module.exports = function(app, passport) {

app.post('/signup', upload.single('image'), passport.authenticate('local-signup', {
    successRedirect : '/login', 
    failureRedirect : '/',
    failureFlash : true 
}));

The image is uploaded in /uploads folder.

But how to get that image and save it in mongodb. I am using passport.js and below is the code for saving post data.

UserModel.js:

var mongoose = require('mongoose');
var Schema = mongoose.Schema;
var userSchema = new Schema({
  image: { 
      data        : Buffer, 
      contentType : String 
  },
  name: {
      type: String,
  },
  email: {
      type: String,
  },
  password: {
      type: String,
  }
});

passport.js:

passport.use('local-signup', new LocalStrategy({
    usernameField : 'email',
    passwordField : 'password',
    passReqToCallback : true
},
function(req, email, password, done) {
    User.findOne({ 'email' :  email }, function(err, user) {
        if (err) {
            //errorLogger.error(err);
            return done(err);
        }

        if (user) {
            return done(null, false, req.flash('signupMessage', 'Email already exists.'));
        } else {
            var newUser = new User();
            //newUser.image = "dont know how to get image from /uploads" 
              newUser.name = req.body.name;
              newUser.email = req.body.email;
              newUser.password = req.body.password;

              newUser.save(function(err) {
                if (err)
                    throw err;
                return done(null, newUser, req.flash('signupMessage', 'User created'));
            });
        }
});

Upvotes: 3

Views: 4810

Answers (2)

SARAN SURYA
SARAN SURYA

Reputation: 554

If you are using images of format 'jpeg / png' and if they are less than 16mb, you can go with this github repo, its a module that helps saving images to mongodb easily, and without the complexity of GRIDFS, but in case if your files are greater than 16mb, you need to use GRIDFS,

This is the link for the github repo for images less than 16 mb (and also works well with react)

https://github.com/saran-surya/Mongo-Image-Converter

Upvotes: 0

Stamos
Stamos

Reputation: 3998

You can create your own middleware that will handle the Upload middleware and get the filename.

I would also suggest to add some random string at the end of uploaded image as protection from same names.

app.post('/signup', middleware , passport.authenticate('local-signup', {
    successRedirect : '/login', 
    failureRedirect : '/',
    failureFlash : true 
}));

middleware

function middleware(req, res, next) {

    var imageName;

    var uploadStorage = multer.diskStorage({
        destination: function (req, file, cb) {
            cb(null, './uploads');
        },
        filename: function (req, file, cb) {
            imageName = file.originalname;
            //imageName += "_randomstring"
            cb(null, imageName);
        }
    });

    var uploader = multer({storage: uploadStorage});

    var uploadFile = upload.single('image');

    uploadFile(req, res, function (err) {
        req.imageName = imageName;
        req.uploadError = err;
        next();
    })
}

and the you can use req.imageName

passport.use('local-signup', new LocalStrategy({
    usernameField : 'email',
    passwordField : 'password',
    passReqToCallback : true
},
function(req, email, password, done) {
    User.findOne({ 'email' :  email }, function(err, user) {
        if (err) {
            //errorLogger.error(err);
            return done(err);
        }

        if (user) {
            return done(null, false, req.flash('signupMessage', 'Email already exists.'));
        } else {
            var newUser = new User();
              newUser.image = req.imageName;
              newUser.name = req.body.name;
              newUser.email = req.body.email;
              newUser.password = req.body.password;

              newUser.save(function(err) {
                if (err)
                    throw err;
                return done(null, newUser, req.flash('signupMessage', 'User created'));
            });
        }
});

Upvotes: 1

Related Questions