Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to add image path in user profile using multer-gridfs-storage ,express, mongodb

below is my file upload code

/** Setting up storage using multer-gridfs-storage */
    var storage = GridFsStorage({
        gfs : gfs,
        filename: function (req, file, cb) {
            var datetimestamp = Date.now();
            cb(null, file.fieldname + '-' + datetimestamp + '.' + file.originalname.split('.')[file.originalname.split('.').length -1]);
        },
        /** With gridfs we can store aditional meta-data along with the file */
        metadata: function(req, file, cb) {
            cb(null, { originalname: file.originalname });
        },
        root: 'ctFiles' //root name for collection to store files into
    });

    var upload = multer({ //multer settings for single upload
        storage: storage
    }).single('file');

    /** API path that will upload the files */
    app.post('/upload', function(req, res) {
        upload(req,res,function(err){
            if(err){
                 res.json({error_code:1,err_desc:err});
                 return;
            }
            console.log(res.file);
            console.log(res[0].file);
             res.json({error_code:0,err_desc:null});
        });
    });

i want to store user name, email and file path in user collection this is my UserSchema

var UserSchema = new Schema({
    name: String,
    email: {
        type: String,
        lowercase: true
    },
    filepath: String,
});

this is how image has stored in collection

{
        "_id" : ObjectId("58fb894111387b23a0bf2ccc"),
        "filename" : "file-1492879681306.PNG",
        "contentType" : "image/png",
        "length" : 67794,
        "chunkSize" : 261120,
        "uploadDate" : ISODate("2017-04-22T16:48:01.350Z"),
        "aliases" : null,
        "metadata" : {
                "originalname" : "Front.PNG"
        },
        "md5" : "404787a5534d0479bd55b2793f2a74b5"
}

this is my expectation result: in user collection i should get data like this

{ 

        "name" :"asdf", 
        "email" : "[email protected]", 
        "filepath":"file/file-1492879681306.PNG"

    }
like image 205
its me Avatar asked Oct 28 '25 10:10

its me


1 Answers

There is a difference between storing in GridFS and storing in an ordinary MongoDb collection. The first is designed to efficiently store files with optionally any additional information while the later allows you to set any schema and store any information. You cannot deal with both the same way.

If what you want is to establish a relationship between a file and a schema in your application, you can do it like this.

  1. Store the desired schema information in the metadata of the file

    Pro: All additional data is stored within the file and deleting the file automatically cleans the additional information.

    Con: Queries could become complex because all of them must be prefixed by a metadata field and all information is mixed together.

    This could be the output of one of your files

    {
        "_id" : ObjectId("58fb894111387b23a0bf2ccc"),
        "filename" : "file-1492879681306.PNG",
        "contentType" : "image/png",
        "length" : 67794,
        "chunkSize" : 261120,
        "uploadDate" : ISODate("2017-04-22T16:48:01.350Z"),
        "aliases" : null,
        "metadata" : {
            "originalname" : "Front.PNG",
            "name" :"asdf",
            "email" : "[email protected]",
            "filepath":"file/file-1492879681306.PNG"
        },
        "md5" : "404787a5534d0479bd55b2793f2a74b5"
    }
    

    Setting information like this is easy, just change the metadata function a little bit.

    ....
    /** With gridfs we can store aditional meta-data along with the file */
    metadata: function(req, file, cb) {
        var metadata = {
            originalname: file.originalname,
            // get this information somehow
            name :"asdf",
            email : "[email protected]",
            filepath:"file/file-1492879681306.PNG"
        };
        cb(null, metadata);
    },
    ....
    

    and this is how you should access them although you could use db.collection or Mongoose to the same purpose.

    const mongodb = require('mongodb');
    const GridFSBucket = mongodb.GridFSBucket;
    const MongoClient = mongodb.MongoClient;
    
    MongoClient.connect('mongodb://yourhost:27017/database').then((db) => {
        const bucket = new GridFSBucket(db, {bucketName: 'ctFiles'});
    
        bucket
            .find({metadata: {'email' : '[email protected]'}})
            .toArray()
            .then((fileInfoArr) => {
                console.log(fileInfoArr);
            });
    });
    

    Then you can use the fileInfo array to create streams and read the file.

  2. Store the schema independently and add an ObjectId field that points to the id of the stored file.

    Pro: Queries and updates over your UserSchema are easier to compose and understand because schema definitions are stored in different collections.

    Con: Now you have two collections to worry about and have to manually keep both in sync; when a file is deleted you should delete the User data and viceversa.

    This is how your UserSchema could look like

     var UserSchema = new Schema({
         name: String,
         email: {
             type: String,
             lowercase: true
         },
         filepath: String,
         fileId: Schema.Types.ObjectId
    });
    

    and this is how you access the files

    UserModel.findOne({'email' : '[email protected]'}, function (err, user) {
        // deal with error
        // store and get the db object somehow
    
        const bucket = new GridFSBucket(db, {bucketName: 'ctFiles'});
    
        // A download stream reads the file from GridFs
        const readStream = bucket.openDownloadStream(user.fileId));
    
        readStream.pipe(/* some writable stream */);
    });
    

Remember that GridFs stores files, therefore you should use streams whenever possible to read and write data handling backpressure correctly.

PD:

Stuff like root belong to GridStore which is obsolete. You should use GridFSBucket whenever possible. The new version of multer-gridfs-storage also deals with bucketName instead of root.

like image 78
devconcept Avatar answered Oct 30 '25 00:10

devconcept



Donate For Us

If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!