Home > Back-end >  How to store and retrieve image using NodeJS and MongoDB?
How to store and retrieve image using NodeJS and MongoDB?

Time:01-01

everyone. I'm still new to NodeJs and Mongodb and i would like some help when it comes to adding and retrieving an image depending on a user in my database. I created this mongoose schema and I have as a field "img" that I would like to use to store images and retrieve images. I've tried using GridFS and multer which i heard could do what i'm looking for but i'm unable to correctly store my image and then retrieve it. I use React as my frontend.

User model :


const mongoose = require("mongoose");
const uniqueValidator = require("mongoose-unique-validator");

const userSchema = mongoose.Schema(
  {
    first: { type: String, required: true },
    last: { type: String, required: true },
    username: { type: String, required: true, unique: true },
    password: { type: String, required: true },
    img: {data: Buffer, type: String },
  },
  { timestamps: true }
);
userSchema.plugin(uniqueValidator);
module.exports = mongoose.model("User", userSchema);

User Controller :

const user = require('../models/user');
var User = require('../models/user');


exports.get_user = async (req, res, next) => {
    const { username, password } = req.body;
    let user_obj = await User.findOne({ username: username, password: password })
    res.status(200).json(user_obj);
}

exports.create_user = async (req, res, next) => {
    const { first, last, username, password, img} = req.body;
    const user_obj = new User({ first: first, last: last, username, password,img: req.file.filename});
     
     
    await user_obj.save();
    res.status(200).json('user creation succeded');
}

User Route :

const express = require("express");
const router = express.Router();
const userController = require('../controllers/userController');
const upload = require('../middleware/upload');

router.post("/create_user", upload.single('img'), userController.create_user);
//router.post("/create_user", userController.create_user);
router.post("/update_user", userController.update_user);
router.post("/get_user", userController.get_user);
router.get("/delete_user/:username", userController.delete_user);


module.exports = router;

Using this code i'm able to store an image but when i try to retrieve it using react as a frontend, the image dosen't render correctly on the browser.

I would really like some help, this is for a school project. Thank you, in advance!

CodePudding user response:

Sorry, I do not have enough points to comment to clarify this. When you say "render", does it look like a bunch of gibberish text on the page? If so, for me, this was due to not sending the correct content type in the header when I served my file from my NodeJS web server. I was sending "text/html" instead of "image/jpg" when a client requested a .jpg image.

CodePudding user response:

Images should be saved as static content then store only the path/url in database


But if we have to save file data directly in DB, here's the code using multer. Only use for file smaller than 16mb. If larger, use GridFS.

Controller

const upload = multer()

app.post("/create_user", upload.single('img'), async (req, res) => {
  const user_obj = new User({
    img: req.file.buffer
  });

  await user_obj.save();
  res.json(user_obj);
});

Model

const userSchema = mongoose.Schema(
  {
    img: { type: Buffer },
  },
);

React on the frontend

function App() {

  const [image, setImage] = useState()

  const toBase64 = uInt8Array => btoa(String.fromCharCode(...uInt8Array));

  useEffect(() => {
    fetch('http://localhost:8000/get_user')
      .then(res => res.json())
      .then(data => {
        setImage(`data:image/jpeg;base64,${toBase64(data.img.data)}`);
      })
  }, [])

  return (
    <>
      {image && <img src={image} alt='logo' />}
    </>
  );
}
  • Related