gridfs-stream icon indicating copy to clipboard operation
gridfs-stream copied to clipboard

TypeError: grid.mongo.GridStore is not a constructor

Open MikhilMC opened this issue 4 years ago • 1 comments

Hi everyone. I was trying out a youtube tutorial of this link. This is my code.

const bodyParser = require("body-parser");
const path = require("path");
const crypto = require("crypto");
const mongoose = require("mongoose");
const multer = require("multer");
const { GridFsStorage } = require("multer-gridfs-storage");
const Grid = require("gridfs-stream");
const methodOverride = require("method-override");

const app = express();

// Middleware
app.use(bodyParser.json());
app.use(methodOverride("_method"));
app.set("view engine", "ejs");

// Mongo URI
const mongoURI = "mongodb://localhost:27017/MongoFileUploads";

// Create mongo connection
const connection = mongoose.createConnection(mongoURI);

// Init GFS
let gfs;

connection.once("open", () => {
  // Init stream
  gfs = Grid(connection.db, mongoose.mongo);
  gfs.collection("uploads");
});

// Create a storage engine
const storage = new GridFsStorage({
  url: mongoURI,
  file: (req, file) => {
    return new Promise((resolve, reject) => {
      crypto.randomBytes(16, (err, buf) => {
        if (err) {
          return reject(err);
        }
        const filename = buf.toString("hex") + path.extname(file.originalname);
        const fileInfo = {
          filename: filename,
          bucketName: "uploads",
        };
        resolve(fileInfo);
      });
    });
  },
});
const upload = multer({ storage });

// @route GET /
// @desc Loads form
app.get("/", (req, res) => {
  res.render("index");
});

// @route POST /upload
// @desc Upload file to DB
app.post("/upload", upload.single("file"), (req, res) => {
  // res.json({ file: req.file });
  res.redirect("/");
});

// @route GET /files
// @desc Display all files in JSON
app.get("/files", (req, res) => {
  gfs.files.find().toArray((err, files) => {
    if (err) {
      console.log(err);
    }

    // Check if files exists
    if (!files || files.length === 0) {
      return res.status(404).json({
        err: "No files exists",
      });
    }

    // Files exists
    return res.json(files);
  });
});

// @route GET /files/:filename
// @desc Display single file object
app.get("/file/:filename", (req, res) => {
  gfs.files.findOne({ filename: req.params.filename }, (err, file) => {
    if (err) {
      console.log(err);
    }

    // File does not exists
    if (!file || file.length === 0) {
      return res.status(404).json({
        err: "No file exists",
      });
    }

    // File exists
    return res.json(file);
  });
});

// @route GET /image/:filename
// @desc Display image
app.get("/image/:filename", (req, res) => {
  gfs.files.findOne({ filename: req.params.filename }, (err, file) => {
    if (err) {
      console.log(err);
    }

    // File does not exists
    if (!file || file.length === 0) {
      return res.status(404).json({
        err: "No image exists",
      });
    }

    // Check if image
    if (file.contentType === "image/jpeg" || file.contentType === "image/png") {
      // Read output to browser
      const readstream = gfs.createReadStream(file.filename);
      readstream.pipe(res);
    } else {
      res.status(404).json({ error: "Not an image" });
    }
  });
});

const port = 5000;

app.listen(port, () => {
  console.log(`Server started on port ${port}`);
});

This is the configuration for this project

{
  "name": "file-upload",
  "version": "1.0.0",
  "description": "",
  "main": "index.js",
  "scripts": {
    "start": "node app.js",
    "dev": "nodemon app.js"
  },
  "keywords": [],
  "author": "",
  "license": "ISC",
  "dependencies": {
    "body-parser": "^1.19.0",
    "ejs": "^3.1.6",
    "express": "^4.17.1",
    "gridfs-stream": "^1.1.1",
    "method-override": "^3.0.0",
    "mongoose": "^6.0.13",
    "multer": "^1.4.3",
    "multer-gridfs-storage": "^5.0.2"
  },
  "devDependencies": {
    "nodemon": "^2.0.15"
  }
}

When I tries to get image using the GET request route /image/:filename, I am getting this error.

/home/mikhil/eth_lab/file-upload/node_modules/gridfs-stream/lib/readstream.js:68 this._store = new grid.mongo.GridStore(grid.db, this.id || new grid.mongo.ObjectID(), this.name, this.mode, options); ^

TypeError: grid.mongo.GridStore is not a constructor at new GridReadStream (/home/mikhil/eth_lab/file-upload/node_modules/gridfs-stream/lib/readstream.js:68:17) at Grid.createReadStream (/home/mikhil/eth_lab/file-upload/node_modules/gridfs-stream/lib/index.js:53:10) at /home/mikhil/eth_lab/file-upload/app.js:125:30 at /home/mikhil/eth_lab/file-upload/node_modules/mongodb/lib/utils.js:508:9 at /home/mikhil/eth_lab/file-upload/node_modules/mongodb/lib/cursor/abstract_cursor.js:477:68 at /home/mikhil/eth_lab/file-upload/node_modules/mongodb/lib/utils.js:508:9 at completeEndSession (/home/mikhil/eth_lab/file-upload/node_modules/mongodb/lib/sessions.js:147:17) at /home/mikhil/eth_lab/file-upload/node_modules/mongodb/lib/sessions.js:157:13 at maybePromise (/home/mikhil/eth_lab/file-upload/node_modules/mongodb/lib/utils.js:494:5) at ClientSession.endSession (/home/mikhil/eth_lab/file-upload/node_modules/mongodb/lib/sessions.js:133:41) [nodemon] app crashed - waiting for file changes before starting...

I tried to search for the solution in stackoverflow, and I got this link. In there, it is saying that, I would have to install an older version of mongoose (degrade from 6.0.13 to 5.13.7). But it would bring the deprication warning. Is there any other way such that, this issue can be avoided?

MikhilMC avatar Nov 30 '21 07:11 MikhilMC

Yeah the problem is gridfs-stream is written 7 years ago and it's using GridStore which is deprecated according to Mongodb doc and it's should be GridFSBucket now. I think the packages really need update

Nguyen130601 avatar Dec 02 '21 14:12 Nguyen130601