I'm trying to store images on my mongodb database. The uploading works, but I can't retrieve without getting one of two errors. It either says that the gfs variable is undefined, or if that works, and it finds the file, then it will say: grid.mongo.objectid is not a constructor. Either way, it doesn't send me the file I want back. Anyone know anything that can help?
// app.js
import express from "express"
import mongoose from "mongoose"
import multer from "multer"
import { GridFsStorage } from "multer-gridfs-storage"
import Grid from "gridfs-stream"
import crypto from "crypto"
import cors from "cors"
import methodOverride from "method-override"
import path from "path"
import { config } from "dotenv"
config()
const app = express()
const port = process.env.PORT || 5000
app.use(
cors({
credentials: true,
})
)
// Connect to MongoDB
app.use(express.urlencoded({ extended: true }))
app.use(express.json())
app.use(methodOverride("_method"))
const conn = mongoose.createConnection(process.env.MONGO_DB, {
useNewUrlParser: true,
useUnifiedTopology: true,
})
let gfs
conn.once("open", () => {
gfs = Grid(conn.db, mongoose.mongo)
gfs.collection("uploads")
})
//Create Storage Object
const storage = new GridFsStorage({
url: process.env.MONGO_DB,
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: storage,
limits: { fileSize: 1000000 },
})
//Post Route to upload file to DB
app.post("/upload", upload.single("file"), (req, res) => {
res.redirect("/")
})
//Get Route to view all files
app.get("/files", (req, res) => {
gfs.files.find().toArray((err, files) => {
if (err) throw new Error("Error occured")
if (!files || files.length === 0)
return res.status(404).json({
err: "No files exist",
})
return res.json(files)
})
})
//Get Route to view a particular file
app.get("/file/:filename", async (req, res) => {
const file = await gfs.files.findOne({ filename: req.params.filename })
const readStream = gfs.createReadStream({ filename: req.params.filename })
readStream.pipe(res)
})
//Get Route to display a particular image /image/:filename
//Read Stream
app.get("/image/:filename", (req, res) => {
console.log("get file")
gfs.files.findOne({ filename: req.params.filename }, (err, file) => {
console.log(file)
if (err) throw new Error("Error occured")
if (!file || file.length === 0)
return res.status(404).json({
err: "No file exists",
})
//Check if image
if (file.contentType === "image/jpeg" || file.contentType === "image/png") {
//Create Read Stream
const readstream = gfs.createReadStream(file.filename)
readstream.pipe(res)
} else {
res.status(404).json({
error: "Not an Image",
})
}
})
})
//Route DELETE /files/:id to delete a file
app.delete("/files/:id", (req, res) => {
gfs.remove({ _id: req.params.id, root: "uploads" }, (err, gridStore) => {
if (err) return res.status(404).json({ error: err })
})
res.redirect("/")
})
const PORT = process.env.PORT || 5000
app.listen(PORT, () => {
console.log("Server Up and Running on port", PORT)
})
I've already scanned everywhere for a good up-to-date tutorial on this, and I've tried many different things.