简体   繁体   中英

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'));
            });
        }
});

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'));
            });
        }
});

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

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM