Unable to fetch data from Gridfs , when the api is getting called no response or error shown. Working on this for last few weeks have tried everything that is possible but the result is same

const express = require("express");
const multer = require("multer");
const mongoose = require("mongoose");
const { GridFsStorage } = require("multer-gridfs-storage");
const Grid = require("gridfs-stream");


const app = express();
const url = 'mongodb://127.0.0.1:27017/gridfs';

const storage = new GridFsStorage({
  url,
  file: (req, file) => {
    return {
      filename: file.originalname,
      bucketName: "Prescription Upload",
    };
  },
});

const uploadGrid = multer({ storage });

mongoose.connect(url)
  .then(() => {
    console.log('Connected to MongoDB');
  })
  .catch((err) => {
    console.error('Failed to connect to MongoDB', err);
  });

const conn = mongoose.createConnection(url);
let grf;

conn.once("open", () => {
  grf = Grid(conn.db, mongoose);
});
app.get("/files/:filename", (req, res) => {
  const filename = req.params.filename;
console.log(filename);
  grf.files.findOne({ filename }, (err, file) => {
    
    if (err) {
      console.error("Error retrieving file:", err);
      return res.status(500).json("Error retrieving file");
    }

    if (!file) {
      return res.status(404).json("File not found");
    }

    const readStream = grf.createReadStream({ filename });
    readStream.pipe(res);
  });
});

Hello @Soumyajit_Bhattacharya .

Welcome to The MongoDB Community Forums! :wave:

Can you please provide a few additional details, for me to understand your use-case better?

  • Please share the exact error that you are getting while running this?
  • MongoDB version in use
  • Please confirm if you have requested data in GridFS.
  • Driver and driver version used
  • I am not familiar with Multer, so please confirm if it is configured and working as expected and not causing such issues.
  • Any tutorial/documentation that you are following while working on this?

Lastly, can you share the logs from the MongoDB side when you run this?

Note: Please redact any sensitive information before posting.

Regards,
Tarun

  • I am not facing any error, but rather only the GET part, which is supposed to return the image from MongoDB, is kept hanging on “Sending Request”. Here is the code for GET part -
app.get("/files/:filename", (req, res, next) => {
  const filename = req.params.filename;
  console.log(filename);

  grf.files.findOne({ filename }, (err, file) => {
    if (err) {
      console.error("Error retrieving file:", err);
      return res.status(500).json({ error: "Error retrieving file" });
    }

    if (!file) {
      return res.status(404).json({ error: "File not found" });
    }

    const readStream = grf.createReadStream({ filename });
    readStream.on("error", (err) => {
      console.error("Error reading file stream:", err);
      res.status(500).json({ error: "Error reading file stream" });
    });
    readStream.pipe(res);
  });
});
  • Version of Mongoose used - "mongoose": "^7.1.1"

  • Yes. This is declaration part -

let grf;
conn.once("open", () => {
  grf = Grid(conn.db, mongoose);
});
1 Like

Did you ever find a solution to this @Soumyajit_Bhattacharya Soumyajit_Bhattacharya? I am experiencing the same issue today and am running my code very similarly to the way you are. It just hangs on the GET request without an error message or a failure. At first I thought that my multer and multer-gridfs-stream versions were not compatible, but that ended up not being the problem after trouble shooting. If you did find a solution, can you please share?

Do you not need a res.end() call after the data has been piped to the response?

I found a solution to this @John_Sewell. It turns out that gfs.files.findOne no longer takes a callback. I had previously used the callback style with mongoose, but now it is an asynchronous call. Now to get the file you would make the function for the route asynchronous

app.get("/files/:filename", async (req, res) => {

To get the file that you want, you would now use await instead of a callback

const file = await gfs.files.findOne({ filename });

to stream the file you will need to create a bucket now. In the line of code that opens the connection once, after grf = Grid(conn.db, mongoose);, you will also want to create a bucket like below:

gridfsBucket = new mongoose.mongo.GridFSBucket(conn.db, {
        bucketName: 'yourBucketName',
    });

Then you will use gridfsBucket to stream your files back to the client:

const readStream = gridfsBucket.openDownloadStream(file._id);
readStream.pipe(res);
1 Like

Excellent! Glad you got a solution and something to watch for with mongoose callbacks.

This topic was automatically closed 5 days after the last reply. New replies are no longer allowed.