node.js - 使用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 函数有表单数据,不知道是什么问题?
解决方案
推荐阅读
- version-control - 无需重新下载即可同步工作区
- apache - MAMP VirtualHost 无法在 Windows 上运行
- python-3.x - Discord.py 说命令丰富的嵌入
- java - 无法将 Java 中的 Azure Function 部署到 Azure 云
- flutter - 在 TableCalendar 包上使用 _onVisibleDaysChanged 时如何获取当前年份和月份
- javascript - 如何连接两个字符串并在ajax调用中传入url
- powerbi - SSAS/PowerBI RS。PBI 中用于显示服务器名称的度量,或 SSAS 表格模型中的字段
- react-navigation - 使用 React Navigation 了解 Stack Navigator 之外的组件中的当前路由是什么?
- typescript - Typescript 中奇怪的类型推断行为
- python - 通过按钮绘制轴数据交换