Babagee
Babagee

Reputation: 45

Uploading images from your React frontend to your Mongo db using express server

I am trying to post pictures from my React frontend to my database using multer in the backend, everything worked fine when I was using postman to upload the images and data, however, on my react frontend I have been having some issues posting pictures to the database. The frontend code is as follows

import React, { useState } from "react";
import axios from "axios";

const Shoes = () => {

    const [name, setName] = useState("");
    const [price, setPrice] = useState("");

    const fileInput = React.createRef();

    const handleName = (e) => {
        setName(e.target.value);
    };
    const handlePrice = (e) => {
        setPrice(e.target.value);
    };

       const onSubmit = async (e) => {
        e.preventDefault();

        const product = {
            name: name,
            price: price,
            productImage: fileInput.current.files[0].name,
        };


        axios
            .post("http://localhost:5000/product/post", product)
            .then((res) => console.log(res.data))
            .catch((err) => console.log(err));

        alert(`Selected file - ${fileInput.current.files[0].name}`);
        console.log(fileInput.current.files[0]);
    };

    return (
        <div>
            <h2>Add Product</h2>

            <form onSubmit={onSubmit}>
                <input
                    type="text"
                    name="name"
                    value={name}
                    onChange={handleName}
                />
                <br />
                <input
                    type="text"
                    name="price"
                    value={price}
                    onChange={handlePrice}
                />
                <br />
                <input type="file" ref={fileInput} />
                <br />
                <input type="submit" value="Submit" />
            </form>

            <hr />
        </div>
    );
};

export default Shoes;

And this is how I used multer in the express backend

const express = require("express");
const router = express.Router();
const multer = require("multer");

const Product = require("../models/Product");

const fileFilter = (req, file, cb) => {
    if (file.mimetype === "image/jpeg" || file.mimetype === "image/png") {
        cb(null, true);
    } else {
        cb("JPEG and PNG only supported", false);
    }
};

const storage = multer.diskStorage({
    destination: function (req, file, cb) {
        cb(null, "./uploads");
    },
    filename: function (req, file, cb) {
        cb(
            null,
            new Date().toISOString().replace(/:/g, "-") + file.originalname
        );
    },
});

const upload = multer({
    storage: storage,
    limts: {
        fileSize: 1024 * 1024 * 5,
    },
    fileFilter: fileFilter,
});

router.get("/", (req, res) => {
    Product.find()
        .select("name productImage -_id ")
        .then((pro) => res.json(pro))
        .catch((err) => res.json({ error: "could not get products", err }));
});

router.post("/post", upload.single("productImage"), async (req, res) => {
    console.log(req.file);
    const product = new Product({
        name: req.body.name,
        price: req.body.price,
        productImage: req.file,
    });

    try {
        const pro = await product.save();
        res.json(pro);
    } catch (err) {
        res.status(400).json({ error: "could not post shoe info", err });
    }
});


module.exports = router;


Whenever I send the picture from my frontend it posts the picture as null, when I console logged it I saw that it's passing the image as undefined. So I was thinking that maybe it requires the path of image and I have been passing it with just the name but I can't seem to find a way to post the image path from the frontend.

Thanks in advance.

Upvotes: 0

Views: 1594

Answers (1)

soumya sunny
soumya sunny

Reputation: 226

File upload in javascript is done using FormData. You are not using FormData but sending the data as an object. Also you are passing just the name of file, not the entire content.

const product = {
        name: name,
        price: price,
        productImage: fileInput.current.files[0] //.name,
    };

Check this SO Post

Upvotes: 1

Related Questions