REACT/MONGODB难以创建一个“item”模型,该模型可以将带有标题、描述和图像的项目上传到mongoDB

pprl5pva  于 2023-08-04  发布在  Go
关注(0)|答案(1)|浏览(82)

我在一个网站上工作,以增加服装项目和显示它们。我的最终目标是能够创建一个带有标题、描述和多张照片的服装文章。现在,我可以为DB创建一个包含标题和描述的条目,但是该文件总是空的,或者在使用该条目上传时根本没有文件。
这是我目前的设置。
型号>项目型号

const mongoose = require('mongoose');
const Schema = mongoose.Schema;

const itemSchema = new Schema({
   title: {type: String},
   description: {type: String},
   files: {type: String} <---I know I dont want this to be string but it wont let me select File of any kind
     
}, {
timestamps: true
});

module.exports = mongoose.model('Item', itemSchema);

字符串
AdditemForm

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

import * as itemsService from '../../utilities/items-service'

export default function AddItemForm() {

    const [fullItem, setFullItem] = useState({
        title: '',
        description: '',
        file: ''
      });
    
      function handleChange(evt) {
        setFullItem({ ...fullItem, [evt.target.name]: evt.target.value });
      }
    
      async function handleSubmit(evt) {
        evt.preventDefault();
        axios.post('/api/items', fullItem)
      .then(response => {
        // Handle the response (e.g., show success message, update UI, etc.)
        console.log('Item uploaded successfully:', response.data);
        })
      .catch(error => {
        // Handle errors (e.g., show error message, etc.)
        console.error('Error uploading item:', error);
        });
      };

    return (
      <>
        <div>This is the AddItemForm page</div>

        <div className="form-container">
            <form autoComplete="off" encType="multipart/form-data" onSubmit={handleSubmit}>
                <label>Title: </label>
                <input type="text" name="title" value={fullItem.title} onChange={handleChange} required />
                <label>Description: </label>
                <input type="text" name="description" value={fullItem.description} onChange={handleChange} required />
                <label>File: </label>
                <input type="file" name="file" value={fullItem.file} onChange={handleChange} required />
                <button type="submit" >Submit</button>
            </form>
        </div>
        
      </>
    )
}


然后我的create函数

async function create(req, res) {
  try{
    const createdItem = await Item.create(req.body);
    res.json(createdItem);

  }  catch(err) {
    res.status(400).json(err);
    console.log(err)
    } 
}


我已经看了几天的视频,所有的例子都超级简单,但对我不起作用。
从我所看到的,Multer不再工作,或者至少我不能让它和我的react版本一起玩。
我也尝试过使用formData将项目发送到DB,但当我这样做时,Mongo根本没有得到任何字段。这是备用additem页

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

const ItemUpload = () => {
  const [title, setTitle] = useState('');
  const [description, setDescription] = useState('');
  const [selectedImage, setSelectedImage] = useState(null);

  const handleTitleChange = (event) => {
    setTitle(event.target.value);
  };

  const handleDescriptionChange = (event) => {
    setDescription(event.target.value);
  };

  const handleFileSelect = (event) => {
    const file = event.target.files[0];
    setSelectedImage(file);
  };

  const handleUpload = () => {
    const formData = new FormData();
    formData.append('title', title);
    formData.append('description', description);
    formData.append('image', selectedImage);

    axios.post('/api/items', formData)
      .then(response => {
        // Handle the response (e.g., show success message, update UI, etc.)
        console.log('Item uploaded successfully:', response.data);
      })
      .catch(error => {
        // Handle errors (e.g., show error message, etc.)
        console.error('Error uploading item:', error);
      });
  };

  return (
    <>
    
    <div>
      <input type="text" placeholder="Title" value={title} onChange={handleTitleChange} />
      <textarea placeholder="Description" value={description} onChange={handleDescriptionChange}></textarea>
      <input type="file" onChange={handleFileSelect} />
      <button onClick={handleUpload}>Upload</button>
    </div>

    </>
  );
};

export default ItemUpload;
`


也尝试过以这种方式提交项目

async function handleSubmit(evt) {
        evt.preventDefault();
        const newFullItem = await itemsService.createItem(fullItem)
 }


呼叫

import * as itemsAPI from './items-api';


export async function createItem(itemData) {
    const newItem = await itemsAPI.createItemRequest(itemData);
    return newItem;
  }


呼叫

import sendRequest from "./send-request";
const BASE_URL = '/api/items';

export function createItemRequest(itemData) {
    const newItem = itemData
    return sendRequest(BASE_URL, 'POST', newItem);
}// send-request.js

export default async function sendRequest(url, method = 'GET', payload = null) {
    const options = { method };
    if (payload) {
      options.headers = { 'Content-Type': 'application/json' };
      options.body = JSON.stringify(payload);
    }
    const res = await fetch(url, options);
    // res.ok will be false if the status code set is not 2xx
    if (res.ok) return res.json();
    throw new Error('Bad Request');
  }

qnakjoqk

qnakjoqk1#

这是我如何使用multer进行单个文件上传。我相信你可以破译它,并适应处理多个图像:
React组分:

import React, { useEffect, useState } from 'react'
        import { Link, useNavigate } from 'react-router-dom'
        import axios from 'axios'
        import { useMediaQuery } from 'react-responsive';
        
        const AdminDashboard = (props) => {
           ...
            const addShoe = (e) => {
                e.preventDefault();
                // try {
                axios.post('http://localhost:8000/api/shoes', shoe, { headers: { 'Content-Type': 'multipart/form-data', }, })
                    .then((res) => {
                        setCount(count + 1)
                        setShoe({
                            name: "",
                            brand: "",
                            gender: "M",
                            price: 0,
                            discountedPrice: 0,
                            image: 0,
                            color: "",
                            size: 0,
                            description: ""
                        })
                        setErrors({})
                    })
                    .catch((err) => {
                        console.log(err)
                        setErrors({
                            name: err.response.data.error.errors?.name,
                            brand: err.response.data.error.errors?.brand,
                            gender: err.response.data.error.errors?.gender,
                            price: err.response.data.error.errors?.price,
                            discountedPrice: err.response.data.error.errors?.discountedPrice,
                            color: err.response.data.error.errors?.color,
                            size: err.response.data.error.errors?.size,
                            description: err.response.data.error.errors?.description,
                            image: err.response.data.error.errors?.image,
                            generic: err.response.data
                        })
                    })
                // }
                // catch (error) {
                //     console.error('Error uploading sneaker:', error);
                // }
            };
        
            const handleChange = (e) => {
                if (e.target.name === 'image') {
                    setShoe({ ...shoe, image: e.target.files[0] });
                } else {
                    setShoe({ ...shoe, [e.target.name]: e.target.value });
                }
            };
        
            
            return (
                <div className='admin-container'>
                    <h2 style={{ textAlign: 'center' }}>Admin Dashboard</h2>
                    <p style={{ textAlign: 'center' }}>Shoe Creator</p>
                    <form className='admin-dash' onSubmit={addShoe}>
                        <div>
                            <div className='form-divs'>
                                {errors?.generic ? <p style={{ color: "red" }}>{errors?.generic?.message}</p> : null}
                                <label>Name</label>
                                {errors?.name ? <p style={{ color: "red" }}>{errors?.name?.message}</p> : null}
                                <input type="text" name="name" placeholder='Name' value={shoe.name} onChange={handleChange} />
                            </div>
                            <div className='form-divs'>
                                <label>Brand</label>
                                {errors?.brand ? <p style={{ color: "red" }}>{errors?.brand?.message}</p> : null}
                                <input type="text" name="brand" placeholder='Brand' value={shoe.brand} onChange={handleChange} />
                            </div>
                            <div className='form-divs'>
                                <label>Color</label>
                                {errors?.color ? <p style={{ color: "red" }}>{errors?.color?.message}</p> : null}
                                <input type="text" name="color" placeholder='Color' value={shoe.color} onChange={handleChange} />
                            </div>
                        </div>
                        <div>
                            <div className='form-divs'>
                                <label>Description</label>
                                {errors?.description ? <p style={{ color: "red" }}>{errors?.description?.message}</p> : null}
                                <input type="text" name="description" placeholder='Description' value={shoe.description} onChange={handleChange} />
                            </div>
                            <div className='form-divs'>
                                <label>Gender</label>
                                {errors?.gender ? <p style={{ color: "red" }}>{errors?.gender?.message}</p> : null}
                                <select style={{ width: '100%', marginTop: '10px' }} name="gender" id="gender" onChange={handleChange}>
                                    <option value="" disabled selected>Select a Gender</option>
                                    <option value="M">M</option>
                                    <option value="F">F</option>
                                </select>
                            </div>
                            <div className='form-divs'>
                                <label>Size</label>
                                {errors?.size ? <p style={{ color: "red" }}>{errors?.size?.message}</p> : null}
                                <input type="number" name="size" value={shoe.size} placeholder='Shoe Size' onChange={handleChange} />
                            </div>
                        </div>
                        <div>
                            <div className='form-divs'>
                                <label>Price</label>
                                {errors?.price ? <p style={{ color: "red" }}>{errors?.email?.message}</p> : null}
                                <input type="number" name="price" value={shoe.price} placeholder='Price' onChange={handleChange} />
                            </div>
                            <div className='form-divs'>
                                <label>Discounted Price</label>
                                {errors?.discountedPrice ? <p style={{ color: "red" }}>{errors?.discountedPrice?.message}</p> : null}
                                <input type="number" placeholder='Discounted Price' name="discountedPrice" value={shoe.discountedPrice} onChange={handleChange} />
                            </div>
                            <div className='form-divs'>
                                {errors?.image ? <p style={{ color: "red" }}>{errors?.image?.message}</p> : null}
                                <input id="file-input" class="file-input-label" type="file" name="image" onChange={handleChange} />
                            </div>
                            <button className='admin-btn' type="submit">Submit</button>
                        </div>
                    </form>
                    <form onSubmit={handleSearch} style={{ textAlign: "center" }}>
                        <input className='search-sneaks' type="text" value={searchQuery} onChange={handleSearchInputChange} placeholder='Sneaker Searcher' />
                        <button className='search-btn' onClick={handleSearch}>Search</button>
                    </form>
                    
                </div>
            )
        }
        
        export default AdminDashboard

字符串
控制器:

const SneakerFinder = require('../models/sneakers.model')
    
    module.exports = {
    
        
        createSneaker: async (req, res) => {
            console.log(req.body)
            try {
                const { name, brand, gender, price, discountedPrice, color, size, description } = req.body;
                const image = req.file.filename;
    
                const sneaker = new SneakerFinder({ name, brand, gender, price, discountedPrice, color, size, description, image });
                console.log(sneaker)
                await sneaker.save();
    
                res.status(201).json({ message: 'Sneaker uploaded successfully!' });
            } catch (error) {
                res.status(500).json({ message: 'Something went wrong creating a sneaker. Please ensure there is an image file', error: error });
            }
        },
        updateSneakerBody: async (req, res) => {
            console.log(req.body)
            try {
                console.log(req.body, "...", req.file)
                const { name, brand, gender, price, discountedPrice, color, size, description } = req.body
    
                const updatedSneaker = await SneakerFinder.findOneAndUpdate(
                    { _id: req.params.id },
                    { name, brand, gender, price, discountedPrice, color, size, description },
                    { new: true },
                    { runValidators: true },
                )
    
                res.status(201).json({ message: '72 Sneaker body updated successfully!', sneaker: updatedSneaker })
                console.log("73", updatedSneaker)
            } catch (error) {
                console.log("75 Something went wrong updating a shoe body", error)
                res.status(500).json({ message: '76 Error updating sneaker body', error: error })
            }
        },
    
        updateSneakerImage: async (req, res) => {
            console.log(req.body)
            try {
                console.log(req.body, "...", req.file)
                const image = req.file ? req.file.filename : null
    
                const updatedSneaker = await SneakerFinder.findOneAndUpdate(
                    { _id: req.params.id },
                    { image },
                    { new: true }
                )
    
                res.status(201).json({ message: 'Sneaker image updated successfully!', sneaker: updatedSneaker })
                console.log(updatedSneaker)
            } catch (error) {
                console.log("Something went wrong updating a shoe image", error)
                res.status(500).json({ message: 'Error updating sneaker image', error: error })
            }
        },


路线:

const uploadMiddleware = require('../middleware/multerMiddleware')
    const SneakerController = require("../controllers/sneakers.controller");
    
    module.exports = (app) => {
        app.get('/api/', SneakerController.index);
        app.get('/api/shoes', SneakerController.getAllSneakers);
        app.get('/api/shoes/:id', SneakerController.getOneSneaker);
        app.post('/api/shoes', uploadMiddleware.single('image'), SneakerController.createSneaker);
        app.put('/api/shoes/:id', SneakerController.updateSneakerBody);
        app.put('/api/shoes/:id/image', uploadMiddleware.single('image'), SneakerController.updateSneakerImage);
        app.delete('/api/shoes/:id', SneakerController.deleteSneaker);
    }


中间件:

const multer = require("multer")

const storage = multer.diskStorage({
    destination: function (req, file, cb) {
        cb(null, "./public/uploads")
    },
    filename: function (req, file, cb) {
        cb(null, file.originalname)
    }
})

const fileFilter = (req, file, cb) => {
    const allowedFileTypes = ['image/png', 'image/jpg', 'image/jpeg', 'image/webp']
    if (allowedFileTypes.includes(file.mimetype)) {
        cb(null, true)
    } else {
        cb(null, false)
    }
}

const uploadMiddleware = multer({
    storage: storage,
    limits: { fileSize: 5000000 },
    fileFilter
})

module.exports = uploadMiddleware

相关问题