首页 > 解决方案 > 使用nodejs和mongodb在reactjs中上传图像文件

问题描述

我有一个包含各种字段和要上传的图像文件的表单。创建 API 的服务器端代码运行良好。服务器代码如下所示。

const express = require("express");
const imageRouter = express.Router();
const mongoose = require('mongoose');
const Image = require('../../models/Ad');
const db = require("../../config/keys").mongoURI;

module.exports = (upload) => {
    const url = db;
    const connect = mongoose.createConnection(url, { useNewUrlParser: true, useUnifiedTopology: true });

    let gfs;

    connect.once('open', () => {
        // initialize stream
        gfs = new mongoose.mongo.GridFSBucket(connect.db, {
            bucketName: "uploads"
        });
    });

    /*
        POST: Upload a single image/file to Image collection
    */

    imageRouter.route('/')
        .post(upload.single('file'), (req, res, next) => {
          let newAd = new Image({
                                username: req.body.username,
                                description:req.body.description,
                                location:req.body.location,
                                title:req.body.title,
                                instructions:req.body.instructions,
                                time:req.body.time,
                                type:req.body.type,
                                subtype:req.body.subtype,
                                date:Date.parse(req.body.date),
                                filename: req.file.filename
                            });


  newAd.save()
  .then(() => res.json('Post added!'))
  .catch(err => res.status(400).json('Error: ' + err));
})
return imageRouter;
}

模型文件如下:

const mongoose = require('mongoose');

const Schema = mongoose.Schema;

const postadSchema = new Schema({
  username: { type: String, required: true },
  description: { type: String, required: true },
  location: { type: String, required: true },
  title: { type: String, required: true },
  type: { type: String,required: true },
  subtype: { type: String,required: true  },
  instructions: { type: String ,required: true},
  time: { type: String,required: true},
  email: { type: String},
  filename: {
        type: String
    },
  date: { type: Date,required: true},
}, {
  timestamps: true,
});



module.exports = Ad = mongoose.model("ad", postadSchema);

这个服务器代码很好。当我在客户端集成相同的内容时,我无法将数据发布到数据库。奇怪的是我没有收到任何错误。它正在刷新页面并清除数据。客户端js文件如下:

import React, { Component } from 'react';
import DatePicker from 'react-datepicker';
import Select from 'react-select';
import { withRouter } from "react-router-dom";
import "react-datepicker/dist/react-datepicker.css";
import PropTypes from "prop-types";
import Navbar from "../../components/layout/Navbar";
import { connect } from "react-redux";
import { postUser } from "../../actions/authActions";
import axios from 'axios';




class PostAd extends Component {
  constructor(props) {
    super(props);

    this.onChangeUsername = this.onChangeUsername.bind(this);
    this.onChangeInstructions = this.onChangeInstructions.bind(this);
    this.onChangeLocation = this.onChangeLocation.bind(this);
    this.onChangeDescription = this.onChangeDescription.bind(this);
    this.onChangeTitle = this.onChangeTitle.bind(this);
    this.onChangeDate = this.onChangeDate.bind(this);
    this.onChangeTime = this.onChangeTime.bind(this);
    this.handleChange = this.handleChange.bind(this);
    this.handleChange1 = this.handleChange1.bind(this);
    this.onFileChange = this.onFileChange.bind(this);
    this.onSubmit = this.onSubmit.bind(this);



    this.state = {
      username: '',
      description: '',
      location:'',
      title: '',
      instructions:'',
      time:'',
      type:'',
      subtype:'',
      date: new Date(),
      types: [],name:'',subname:'',
      subtypes:[],
      selectedFile: null,
      filename:''
    }

  }

  componentDidMount() {

    const { user } = this.props.auth;

    const options = [
      { label: "Donate", value: "donate" },
      { label: "Want", value: "want" },
      { label: "Other", value: "other" }
    ];


        const suboptions = [
          { label: "Grocery", value: "grocery" },
          { label: "Prepared food", value: "preparedfood" },
          { label: "Fruits", value: "fruits" },
          { label: "Other", value: "other" }
        ];


   this.setState({

     username: user.name.split(" ")[0],
     types:options,
     subtypes:suboptions

   });
 }
  componentWillReceiveProps(nextProps) {
    if (nextProps.errors) {
      this.setState({
        errors: nextProps.errors
      });
    }
  }



  handleChange(e){
    // console.log('handleChange');
   this.setState({type:e.value, name:e.label})

  }

  handleChange1(e){
    // console.log('handleChange');
   this.setState({subtype:e.value, subname:e.label})

  }

  onFileChange = event => {

      // Update the state
      this.setState({ selectedFile: event.target.files[0],
      filename:event.target.files[0]

      });

    };
  onChangeUsername(e) {
     this.setState({
       username: e.target.value
     });
   }

   onChangeLocation(e) {
      this.setState({
        location: e.target.value
      });
    }

   onChangeDescription(e) {
     this.setState({
       description: e.target.value
     });
   }

   onChangeType(e) {
     this.setState({
       type:e.value
     });
   }

   onChangeSubType(e) {
     this.setState({
       subtype:e.value
     });
   }

   onChangeTitle(e) {
     this.setState({
       title: e.target.value
     });
   }

   onChangeInstructions(e) {
     this.setState({
       instructions: e.target.value
     });
   }

   onChangeTime(e) {
     this.setState({
       time: e.target.value
     });
   }

   onChangeDate(date) {
     this.setState({
       date: date
     });
   }
  uploadImage = () => {


        let formData = new FormData();
        formData.append('username', this.state.username);
        formData.append('location', this.state.location);
        formData.append('file', this.state.selectedFile);
        formData.append('description', this.state.description);
        formData.append('type', this.state.type);
        formData.append('subtype', this.state.subtype);
        formData.append('title', this.state.title);
        formData.append('time', this.state.time);
        formData.append('date', this.state.date);


        axios.post('http://localhost:5000/api/post', formData)
            .then((response) => {
              console.log('success');
              //  response.data.success ? alert('File successfully uploaded') : alert('File already exists');
              //  this.props.history.push("/list")
              //  this.fetchRecent();
            })
            .catch(err =>{ alert('Error: ' + err)
             console.log('fail'); }
          );
    }
render() {


    return (
      <div>
      <Navbar />
        <div className="container valign-wrapper" >
        <div className="row" style={{ alignItems: "center-align" , marginTop : "4rem"}}>
        <div className="col">
        <h4>
           <b>Welcome</b> {this.state.username}
        </h4>
      </div>
      </div>
        </div>
    <div className="container" >
        <h5>Post New Ad</h5>
          <form >
          <div className="form-group">
            <label>Username: </label>
            <input  type="text"
                required
                className="form-control"
                value={this.state.username}
                onChange={this.onChangeUsername}


                />
          </div>

          <div className="form-group">
            <label>Title: </label>
            <input
                type="text"
                className="form-control"
                  onChange={this.onChangeTitle}
                value={this.state.title}

                />
          </div>
          <div className="form-group">
            <label>Pickup Location: </label>
            <input
                type="text"
                className="form-control"
                  onChange={this.onChangeLocation}
                value={this.state.location}

                />
          </div>
          <div className="form-group">
            <label>Description: </label>
            <input  type="text"
                required
                className="form-control"
                  onChange={this.onChangeDescription}
                  value={this.state.description}

                />
          </div>
          <div className="form-group">
            <label>Pickup Instructions: </label>
            <input
                type="text"
                className="form-control"
                  onChange={this.onChangeInstructions}
                value={this.state.instructions}

                />
          </div>
          <div className="form-group">
            <label>Category: </label>
            <Select ref="userInput"
                required
                className="form-control"
                onChange={this.handleChange.bind(this)}
                options={this.state.types}
                />

          </div>
          <div className="form-group">
            <label>Sub Category: </label>
            <Select ref="userInput"
                required
                className="form-control"
                onChange={this.handleChange1.bind(this)}
                options={this.state.subtypes}
                />
          </div>

         {/*  <span class="label label-default" style={{
                              marginTop: "1rem",
                              fontSize: 20
                            }}>Type</span>
                            <input
                                type="text"
                                className="form-control"
                                  onChange={this.onChangeType}
                                value={this.state.type}

                                />*/}

          <div className="form-group">
            <label>Pickup Time: </label>
            <input
                type="text"
                className="form-control"
                  onChange={this.onChangeTime}
                value={this.state.time}

                />
          </div>
          <div className="form-group">
            <label>Pickup Date: </label>
            <div>
              <DatePicker
                onChange={this.onChangeDate}
                selected={this.state.date}

              />
            </div>
              <br />
                <br />
            <div className="form-group">
              <label>Select Photo</label>
              <br />
              <input
              type="file"
              className="form-control"
              multiple
              onChange={this.onFileChange} />
            </div>
          </div>
            <br />
              <br />
                <br />

          <div className="form-group">
            <input type="submit" onClick={this.uploadImage} value="Submit" className="btn btn-primary" />
          </div>
        </form>
      </div>
      </div>
    )
  }
}

//export default PostAd;

PostAd.propTypes = {
  postUser: PropTypes.func.isRequired,
  auth: PropTypes.object.isRequired
};

const mapStateToProps = state => ({
  auth: state.auth
});

export default connect(
  mapStateToProps,
  { postUser }
)(withRouter(PostAd));

uploadimage 函数有表单数据,不知道是什么问题?

标签: node.jsreactjsmongodbimagefile-upload

解决方案


推荐阅读