Gridfs bucket and collection issue

41 Views Asked by At

So I'm still trying to make a file upload and download system with gridfs and multer. I have a question regarding where I need to specify the collection, and bucket names. I put the collection that I want to use in the url in my .env file. I also specified it when creating my GridFsStorage under the bucketname property. This is how I want it to be structured: a bucket called "picture_upload" with collections called, "uploads.files" and "uploads.chunks" My code is below:

// 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 /**@type {Grid.Grid}*/ gfs, /**@type {mongoose.mongo.GridFSBucket} */ gridfsBucket
conn.once("open", () => {
  gridfsBucket = new mongoose.mongo.GridFSBucket(conn.db)
  gfs = Grid(conn.db, mongoose.mongo)
  gfs.collection("picture_upload")
})

//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,
          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", async (req, res) => {
  const files = await gfs.files.find().toArray()

  if (!files) 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 })
  console.log(file)
  const readStream = gridfsBucket.openDownloadStream(file._id)
  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

const PORT = process.env.PORT || 5000

app.listen(PORT, () => {
  console.log("Server Up and Running on port", PORT)
})

This is a pretty hard question so please if you have any info please ask! Thanks

I already tried putting the collection name in the url, and various places where it asks for it.

0

There are 0 best solutions below