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!
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);
});
-
Not sure what do you mean by Driver version.
-
Multer is working fine.
-
I have referred to MongoDB documentation.
Link - GridFS - Retrieve File Information
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);
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.