Search code examples
node.jsmongoose-schemamultermulter-gridfs-storage

Multer gridfs storage referencing uploaded file to a new collection


Uploaded file using multer gridfs storage i want to reference it to newly created collection (movies). The fileID i referenced to the uploaded file is not the same with the uploaded file, even with that the movies collection is not saved on to the database. The fileID i referenced to the uploaded file is not the same with the uploaded file, even with that the movies collection is not saved on the database

//movie schema
    const mongoose = require('mongoose');
    const Schema = mongoose.Schema;

    const MovieSchema = new Schema({
    	description: {
    		type: String,
    	},
    	category: {
    		type: String,
    	},
    	token: {
    		type: String,
    	},
    	fileID: {
    		type: Schema.Types.ObjectId,
    		ref: "contents.files"
    	}
    });

    module.exports = movies = mongoose.model('movies', MovieSchema);



    let gfs;

    conn.once('open', () => {
        gfs = Grid(conn.db, mongoose.mongo);
        gfs.collection('contents');

    });



    const storage = new GridFsStorage({
        url: config.db,
        file: (req, file) => {
            return new Promise((resolve, reject) => {
            
                    const filename = req.body.fileName + path.extname(file.originalname);
                    const Description = req.body.Description
                    const fileInfo = {
                        filename: filename,
                        bucketName: 'contents',
                        metadata: req.body,
                        
                    }
                    resolve(fileInfo, Description);
                
            });
        }
    });
    const   upload = multer({
        storage
    });
    router.get('/', (req, res) => {
        res.render('index');
        console.log(req.body)
    });

    //** uploading file to the db */

    router.post('/', upload.any(), (req, res) => {
        
          
        const movie = new movies({
            description: "test",
            category: "test",
            fileID: gfs.files.id
        })
        
          movie.save()
    });

The fileID is different from uploaded file Id and also the collection is not saved on the DB The fileID is different from uploaded file Id and also the collection is not saved on the DB The fileID is different from uploaded file Id and also the collection is not saved on the DB


Solution

  • It doesn't work because you are making this more complicated than it needs to be. The references in your file are unnecessary. You can accomplish the same with this code.

    //movie schema
    const mongoose = require('mongoose');
    const Schema = mongoose.Schema;
    
    const MovieSchema = new Schema({
      description: {
        type: String,
      },
      category: {
        type: String,
      },
      token: {
        type: String,
      },
      fileID: {
        type: Schema.Types.ObjectId, // There is no need to create references here
      }
    });
    
    module.exports = movies = mongoose.model('movies', MovieSchema);
    
    const storage = new GridFsStorage({
      url: config.db,
      file: (req, file) => {
        return new Promise((resolve, reject) => {  
          // if you are using a separate collection to store data 
          // there is no need to save this information on the metadata
          // because you'll probably never use it
          const filename = req.body.fileName + path.extname(file.originalname);
          const fileInfo = {
            filename: filename,
            bucketName: 'contents'
          }
          resolve(fileInfo);
        });
      }
    });
    const upload = multer({
      storage
    });
    
    router.get('/', (req, res) => {
      res.render('index');
      console.log(req.body)
    });
    
    //** uploading file to the db */
    router.post('/', upload.any(), (req, res) => {
      const movie = new movies({
        description: req.body.Description,
        category: req.body.Category,
        // Grab the file id that was stored in the database by the storage engine as the reference to your file
        fileID: req.file._id
      })
    
      movie.save()
    });

    You shouldn't use uploads.any(). This will accept any incoming file. Instead you should use array, single or fields depending on how many files you sent and the field names you used to send them.

    To read that file from the database later you only have to query your Movies collection and the fileId field has an identifier you can pass to GridfsBucket in the openDownloadStream and pipe that stream to the response giving back to the user the file that was stored with that id or to use in whatever business logic your application has.