0

Express, mongoDB, mongoose and multer. I have one form(Note: without image), which I am able to upload to my database and express server is also working good while uploading.

But I have one another form with image and so I am using multer.

While uploading that I am getting following two errors:

500 Internal Server Error

Cast to string failed for value "{ product_name: 'sample product', sub_category: 'Sample' }" at path "product_name" for model "product" [0] { [0] product_image: { product_image: {} }, [0] sub_category: { sub_category: 'Sample', product_name: 'sample product' }, [0] product_name: { product_name: 'sample product', sub_category: 'Sample' }, [0] product_specs: [ { specification: 'Density', specvalue: '500' } ] [0] } ```

Just two know prototypes of each input field, I am sharing screenshot of console.log I have used in Product upload file at line no 65- console.log

I am sharing my code for following- 1 Mongoose Schema file Product.js 2 React form -Productupload file, 3 route file for route(/product), 4 server.js, 5 db.js

I want to know: Is there any error due to prototype not matching of Schema and my req.body with each other? Is My Multer code ok?, I have also commented Grid-fs code because previously I was using it, but as that was giving me the error, then I changed my code. shall I switch back to grid code? Is there anything else needed to upload image to my backend.

Thank you for bearing till now, Hope someone will help me, Ready to share code Sandbox If needed. Please help someone.

Mongoose Schema

```

    const mongoose = require("mongoose");
    
    const ProductSchema = new mongoose.Schema({
      sub_category: {
        type: String,
        required: true,
      },
      product_image: {
        type: String,
        required: true,
      },
      product_name: {
        type: String,
        required: true,
      },
      product_specs: {
        type: [],
        required: true,
      },
    });
    module.exports = Product = mongoose.model("product", ProductSchema);

```

React Form Product Upload File

```

    import React, { useState } from "react";
    import FormInput from "../Forminput/forminput";
    import CustomButton from "../Custombutton/custombutton";
    import axios from "axios";
    
    const ProductUpload = () => {
      const [sub_category, setSub_category] = useState({ sub_category: "" });
    
      const [product_name, setProduct_name] = useState({ product_name: "" });
    
      const [product_image, setProduct_image] = useState("");
    
      const [product_specs, setProduct_specs] = useState([
        {
          specification: "",
          specvalue: "",
        },
      ]);
      
      const imageSelectedHandler = (event) => {
        setProduct_image({ product_image: event.target.files[0] });
      };
    
      const handleChange1 = (e) => {
        const { name, value } = e.target;
    
        setSub_category({ ...sub_category, [name]: value });
        setProduct_name({ ...product_name, [name]: value });
      };
    
      const handleChange2 = (e, i) => {
        const { name, value } = e.target;
    
        const p_specs = [...product_specs];
        p_specs[i][name] = value;
        setProduct_specs(p_specs); //This is 100% right.
      };
    
      //to add extra input field
      const addClick = () => {
        const p_specs = [...product_specs];
        p_specs.push({ specification: "", specvalue: "" });
        setProduct_specs(p_specs);
      };
      //to remove extra input field
      const removeClick = (i) => {
        const p_specs = [...product_specs];
        p_specs.splice(i, 1);
        setProduct_specs(p_specs);
      };
      const handleSubmit = async (event) => {
        event.preventDefault();
        const newProduct = {
          product_image,
          sub_category,
          product_name,
          product_specs,
        };
        console.log(newProduct); //getting this in console.
        try {
          const config = {
            headers: {
              "Content-Type": "application/json",
            },
          };
          const body = JSON.stringify(newProduct);
    
          const res = await axios.post("/api/product", body, config);
          console.log(res.data);
        } catch (error) {
          console.error(error.response.data);
        }
      };
    
      const createUI = () => {
        return product_specs.map((item, i) => {
          return (
            <div key={i} className="inputgroup">
              <FormInput
                type="text"
                name="specification"
                handleChange={(e) => handleChange2(e, i)}
                value={item.specification}
                label="specification"
                required
                customwidth="300px"
              ></FormInput>
              <FormInput
                type="text"
                name="specvalue"
                handleChange={(e) => handleChange2(e, i)}
                value={item.specvalue}
                label="specification values seperated by quomas"
                required
              ></FormInput>
              <CustomButton
                onClick={() => removeClick(i)}
                type="button"
                value="remove"
                style={{ margin: "12px" }}
              >
                Remove
              </CustomButton>
            </div>
          );
        });
      };
      return (
        <div className="container">
          <form
            action="/product" //rout name
            method="post"
            className="form"
            onSubmit={handleSubmit}
            encType="multipart/form-data"
          >
            <h3 style={{ color: "roboto, sans-serif" }}>
              Add new product to the database
            </h3>
            <div
              style={{
                display: "flex",
                height: "200px",
                width: "200px",
                border: "2px solid #DADCE0",
                borderRadius: "6px",
                position: "relative",
              }}
            >
              <input
                // style={{ display: "none" }}
                type="file"
                accept="image/*"
                onChange={imageSelectedHandler}
                multiple={false}
                name="product_image"
              />
              <div>
                <img
                  style={{
                    width: "100%",
                    height: "100%",
                  }}
                  alt="#"
                />
              </div>
            </div>
            <FormInput
              type="text"
              name="sub_category"
              handleChange={handleChange1}
              value={sub_category.sub_category}
              label="select from subcategories"
              required
            ></FormInput>
    
            <FormInput
              type="text"
              name="product_name"
              handleChange={handleChange1}
              value={product_name.product_name}
              label="product name"
              required
            ></FormInput>
            {console.log(product_image)}
            {console.log(product_name)}
            {console.log(product_specs)}
            {createUI()}
            <div>
              <CustomButton
                onClick={addClick}
                type="button"
                style={{ margin: "14px" }}
              >
                Add More Fields
              </CustomButton>
              <CustomButton type="submit" style={{ margin: "12px" }}>
                Upload Product
              </CustomButton>
            </div>
          </form>
        </div>
      );
    };
    export default ProductUpload;

```

Route product

```

    const express = require("express");
    const router = express.Router();
    const Product = require("../../models/Product");
    const { check, validationResult } = require("express-validator");
    //const GridFsStorage = require("multer-gridfs-storage");
    const multer = require("multer");
    const path = require("path");
    
    const Storage = multer.diskStorage({
      destination: "./client/public/uploads/",
      filename: (req, file, cb) => {
        cb(
          null,
          file.filename + "_" + Date.now() + path.extname(file.originalname)
        ); //fieldname will automatically get input filed name value in our case product_omage
      },
    });
    
    //middleware
    const upload = multer({ storage: Storage }).single("product_image");
    
    /*const storage = new GridFsStorage({
      db: connectDB(),
    });
    const upload = multer({ storage });
    module.exports = upload;*/
    
    // @route GET api/Product
    router.get("/", (req, res) => res.send("Product route"));
    
    // @route POST api/Product
    
    router.post(
      "/",
      [
        check("sub_category", "subcategory is required").not().isEmpty(),
        check("product_name", "product name is required").not().isEmpty(),
      ],
      upload,
      async (req, res) => {
        const errors = validationResult(req);
        console.log("req");
        if (!errors.isEmpty()) {
          return res.status(400).json({ errors: errors.array() });
        }
    
        const {
          sub_category,
          product_name,
          product_image,
          product_specs,
        } = req.body;
    
        console.log(req.body);
        console.log(req.body);
        try {
          //See if product exists
          let product = await Product.findOne({ product_name }); // Product.findOne() is mongo db query
    
          if (product) {
            return res
              .status(400)
              .json({ errors: [{ msg: "Product already exists" }] });
          }
    
          //New product instance will be created and once user.save() command is given user will be created in mongodb database.
          product = new Product({
            sub_category,
            product_name,
            product_image,
            product_specs,
          });
    
          await product.save();
        } catch (err) {
          console.error(err.message);
          res.status(500).send("Server error");
        }
      }
    );
    module.exports = router;

```

db file

```

    const mongoose = require("mongoose");
    const config = require("config");
    const db = config.get("mongoURI");
    
    const connectDB = async () => {
      try {
        await mongoose.connect(db, {
          useUnifiedTopology: true,
          useNewUrlParser: true,
          useCreateIndex: true,
          useFindAndModify: false,
        });
    
        console.log("MongoDB connected...");
      } catch (err) {
        console.error(err.message);
        process.exit(1);
      }
    };
    
    module.exports = connectDB;

```
marc_s
  • 732,580
  • 175
  • 1,330
  • 1,459

0 Answers0