Gridfs file retrieval does not send the file back

27 views Asked by At

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.

0

There are 0 answers