reactjs - 使用 multer 进行图像上传时上传表单的问题。错误是Cast to string failed for value and internal server error
问题描述
Express、mongoDB、mongoose 和 multer。我有一个表格(注意:没有图片),我可以将其上传到我的数据库,并且快递服务器在上传时也能正常工作。
但是我有另一种带有图像的表格,所以我正在使用 multer。
上传时出现以下两个错误:
500内部服务器错误
模型“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' ,规范值:'500'}][0]}```
每个输入字段只有两个知道原型,我正在分享我在第 65 行的产品上传文件中使用的 console.log 的屏幕截图-
我正在分享我的以下代码 - 1 Mongoose Schema 文件 Product.js 2 React 表单 -Productupload 文件,3 路由文件(/产品),4 server.js,5 db.js
我想知道:是否由于原型与 Schema 和我的 req.body 不匹配而导致任何错误?我的 Multer 代码可以吗?,我还评论了 Grid-fs 代码,因为以前我使用过它,但是因为这给了我错误,所以我更改了我的代码。我应该切换回网格代码吗?是否还需要将图像上传到我的后端。
感谢您一直到现在,希望有人能帮助我,如果需要,准备分享代码沙盒。请帮助某人。
猫鼬模式
```
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 产品上传文件
```
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;
```
路线产品
```
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;
```
数据库文件
```
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;
```
解决方案
推荐阅读
- javascript - 当包含在自定义可折叠 div 中时,Jquery 选择不显示数据占位符
- google-analytics - Google Analytics:实时显示事件,但不在报告中
- java - 不可变类中的方法在初始化时修改初始化变量?JAVA
- firebase - 在firebase中使用facebook登录react native不起作用,但收到令牌
- unix - 如何在 curl 中处理 302 http 状态代码
- python - 如何在 Tensorflow 中获得 LSTM 的密集层输出?
- pandas - 如何按天聚合熊猫数据框
- c# - ASP Core 2 如何更改(更新)活动用户的声明
- express - 将 HTTP 快速重定向到 HTTPS
- f# - fsi.commands 有参考吗?