3

I am using mongoose with node.js to find a document and update its properties but everytime i do so there is some sort of error which is not logging into the console.It is some issue with multer. Can anyone guess what am id doing wrong?

My schema:

const mongoose = require('mongoose');

const UserSchema = new mongoose.Schema({
    name : {
        type: String,
        required: true
    },
    email : {
        type: String,
        required: true
    },
    password : {
        type: String,
        required: true
    },
    details: {
    type: Object,
},
profile_img: {
    data: String,
    contentType: String,
}
})

const User = mongoose.model('User',UserSchema);

module.exports = User

Multer code:

var fs = require('fs');
var path = require('path');

var multer = require('multer');
 

//store images in db 
var storage = multer.diskStorage({
    destination: (req, file, cb) => {
        cb(null, 'uploads')
    },
    filename: (req, file, cb) => {
         cb(null, new Date().toISOString().replace(/:/g, '-')+ file.originalname);
    }
});

const fileFilter = (req, file, cb) => {
  // reject a file
  if (file.mimetype === 'image/jpeg' || file.mimetype === 'image/png') {
    cb(null, true);
  } else {
    cb(null, false);
  }
};

const upload = multer({
  storage: storage,
  fileFilter: fileFilter
});

Route:

router.post('/profile-chooser/developer/:method',upload.single('profile_photo'),ensureAuthenticated,(req,res) => {
  
        //do db stuff
        User.findOneAndUpdate({ "_id": mongoose.Types.ObjectId(req.user._id) },
         { "$set": 
            { 
                "details": {
                    "Some stuff": "update itttt"
                },
                "profile_img": {
                    "data": fs.readFileSync(path.resolve(__dirname, '../uploads/' + req.file.filename)),
                    "contentType": 'image/png'
                }
            }
        })
        .exec(function(err, user){
            if(err) {
                console.log(err);
                res.status(500).send(err);
            } else {
                res.status(200).send(user);
            }
        });
    })  

I am sure this a problem with multer because when i changed fs.readFileSync(path.resolve(__dirname, ../uploads/ + req.file.filename)) this line into string and also removed upload.single(profile_photo) it magically worked.

Can anyone please help me out.

Your fast response will be highly appreciated.

Thanks in advance.

Saswat
  • 180
  • 4
  • 13
  • How are you checking your collection in mongodb? – tbking Aug 26 '21 at 18:34
  • `_id: req.user._id` - if _id is automatically generated, it will be ObjectId, while req.user._id is almost certainly String. See https://stackoverflow.com/a/55874520/2282634 – Joe Aug 27 '21 at 00:32
  • @tbking i am checking it through the mongodb ui – Saswat Aug 27 '21 at 06:55
  • @Joe i have done that still i am seeing the error when i go to the users collection in my mongodb ui - `There was a problem retrieving data from this collection. Check your query and try again.` i think its a problem with the structure of my schema and how am i iterating over it – Saswat Aug 27 '21 at 07:16
  • If you think it could be a multer issue (which I have no idea if that's the case), you can try temporarily commenting out code associated with multer + recreate database. – Gynteniuxas Aug 28 '21 at 08:08
  • @GytisTG thank god it was an issue with multer. But can anyone tell me what's the issue otherwise there would be no point of it – Saswat Aug 28 '21 at 13:05
  • Since I haven't used that, I have no idea... But since you know the issue, perhaps someone encountered the same issue before. – Gynteniuxas Aug 28 '21 at 13:49

1 Answers1

0

I have figured out. Use multer with multer-gridfs-storage and grid-fs-stream to read/write photos into the db.

Create a middlewares folder and add these lines of code:

const multer = require("multer");
const {GridFsStorage} = require("multer-gridfs-storage");

const storage = new GridFsStorage({
    url: process.env.CONNECTION_URL,
    options: { useNewUrlParser: true, useUnifiedTopology: true },
    file: (req, file) => {
        const match = ["image/png", "image/jpeg"];

        if (match.indexOf(file.mimetype) === -1) {
            const filename = `${Date.now()}-any-name-${file.originalname}`;
            return filename;
        }

        return {
            bucketName: "photos",
            filename: `${Date.now()}-any-name-${file.originalname}`,
        };
    },
});

module.exports = multer({ storage });

Wherever you are posting the data.

Add this piece of middleware after requiring it:

upload.single('profile_photo')

Grid fs stream allows us to read/write into the collections.

If you want to give your collection a name:

let gfs;

const conn = mongoose.connection;
conn.once("open", function () {
    gfs = Grid(conn.db, mongoose.mongo);
    gfs.collection("photos");
});

Yup, that's it. You have successfully learned to write alphabets!

External links (please refer to these links in the order if you are serious).

Complete reference for beginners

For advanced usage:

Multer docs(well written)

Grid-fs-storage(the core of our project)

Grid-fs-stream

Samet Sökel
  • 2,515
  • 6
  • 21
Saswat
  • 180
  • 4
  • 13