首页 > 解决方案 > 我想将带有文本的图像从表单上传到快速服务器

问题描述

我正在使用react,express,mongodb,我想将用户输入的表单数据保存到我的数据库中,我已经到了只保存文本字段并且响应是状态代码200但是当我尝试添加图像时它给了我 500 并且只保存了文本字段,我已经尝试了一切,但无法掌握缺少的内容。我正在使用 multer 和 fetch。

这是客户端

  import React , {Component} from 'react';
import AdminHeader from './AdminHeader';
import AdminFooter from './AdminFooter';
import { Label, Button, Row, Col, Form } from 'reactstrap';
import { baseUrl } from '../shared/baseUrl';
import axios from 'axios';
class AddAppart extends Component {
  constructor(props){
    super(props);
    this.state = {
      areaName: '' ,
      description: '',
      shortDescription: '',
      price: '',
      imageFile: null
    };
    this.onChange = this.onChange.bind(this);
    this.handleSubmit = this.handleSubmit.bind(this);
  }
  onChange(e) {
      if (e.target.id === 'areaName') {
        this.setState({ areaName: e.target.value });
    } else if (e.target.id === 'description') {
        this.setState({ description: e.target.value });
    } else if (e.target.id === 'shortDescription') {
        this.setState({ shortDescription: e.target.value });
    } else if (e.target.id === 'price') {
        this.setState({ price: e.target.value});
        console.log(e.target.value);
    }else if (e.target.id === 'imageFile') {
      this.setState({ imageFile: e.target.files[0]});
      console.log(e.target.value);
    }
  }
  handleSubmit(e) {
    e.preventDefault();
    fetch((baseUrl+'appartments/'), {
      method: 'POST',
      headers: {
        'Accept': 'application/json', 
        'Content-Type': 'application/json'
      },
      body: JSON.stringify({
        areaName: this.state.areaName,
        description: this.state.description,
        shortDescription: this.state.shortDescription,
        price: this.state.price,
        image: this.state.imageFile
      }),
    })
    this.setState({
      areaName: '' ,
      description: '',
      shortDescription: '',
      price: ''
    });
  }
  // handleSubmitFile(){
  //   fetch((baseUrl+'sendfiles'), {
  //     method: 'POST',
  //     body: JSON.stringify({
  //       imageFile: this.state.imageFile
  //     })
  //   })
  // }
  handleSubmitForm(){

      let data = new FormData();
      data.append("imageFile", this.state.imageFile);
      data.set("shortDescription", this.state.shortDescription);
      data.set("areaName",this.state.areaName);
      data.set("description",this.state.description);
      data.set("price",this.state.price);
      fetch((baseUrl+'appartments/'), {
      method: 'POST',
      body: data
    })
    this.setState({
      areaName: '' ,
      description: '',
      shortDescription: '',
      price: ''
    });
  }
  render(){
    return(
      <>
        <AdminHeader />
        <div className="container">
          <h3>Enter Appartment Information</h3>
          <hr />
          <Form onSubmit={this.handleSubmit} id="MyForm">
            <Row className="form-group">
              <Col>
                <Label htmlFor="areaName">Area Name</Label>
                <input model=".areaName" type="text" onChange={this.onChange} id="areaName" className="form-control" innerRef={(input) => this.areaName = input}></input>  
              </Col>
            </Row>
            <Row className="form-group">
              <Col>
                <Label htmlFor="description">Description</Label>
                <input model=".description" type="text" onChange={this.onChange} id="description" className="form-control" innerRef={(input) => this.description = input}></input>  
              </Col>
            </Row>
            <Row className="form-group">
              <Col>
                <Label htmlFor="shortDescription">Short Description</Label>
                <input model=".shortDescription" type="text" onChange={this.onChange} id="shortDescription" className="form-control" innerRef={(input) => this.shortDescription = input}></input>  
              </Col>
            </Row>
            <Row className="form-group">
              <Col>
                <Label htmlFor="price">Price</Label>
                <input model=".price" type="number" id="price" onChange={this.onChange} className="form-control" innerRef={(input) => this.price = input}></input>
              </Col>
            </Row>
            <Row className="form-group">
              <Col>
                <Label htmlFor="imagesUpload">Images Upload</Label>
                <input model=".imageFile" type="file" multiple id="imageFile" className="form-control" innerRef={(input) => this.imageFile = input}></input>
              </Col>
            </Row>
            <Button type="submit" className="bg-primary">Submit</Button>
          </Form>
        </div>
        <AdminFooter />
      </>
    );
  }
}

export default AddAppart;


如您所见,我尝试使用 FormData 和另一个请求 url

这是服务器端

const storage = multer.diskStorage({
    destination: (req, file, cb) => {
        cb(null, 'public/images');
    },

    filename: (req, file, cb) => {
        cb(null, file.originalname)
    }
});

const imageFileFilter = (req, file, cb) => {
    if(!file.originalname.match(/\.(jpg|jpeg|png|gif)$/)) {
        return cb(new Error('You can upload only image files!'), false);
    }
    cb(null, true);
};

const upload = multer({ storage: storage, fileFilter: imageFileFilter});

const appartRouter = express.Router();

appartRouter.use(bodyParser.json());


appartRouter.route('/')
.options(cors.corsWithOptions, (req,res) => {
    res.sendStatus(200);
})
.post(cors.corsWithOptions,upload.array('image'), (req,res,next) =>{
    Appartments.create(req.body)
    .then((appartment) => {
        var files = [].concat(req.files);
        for(var i = 0; i < files.length; i++){
          file = files[i];
          appartment.image.push({"image": file.path});
        }
        appartment.save();
        console.log('Appartment Created ', appartment);
        res.statusCode = 200;
        res.setHeader('Content-Type', 'multipart/form-data');
        res.json(appartment);
    }, (err) => next(err))
    .catch((err) => next(err));
})

当我评论将文件保存到数据库的循环时,状态代码 200 当它工作时给出 500 并且在这两种情况下都只保存文本字段

编辑:我找到了一种使用 axios 和表单数据的方法,并且在发布时,状态变为 200 可以,但图像数组字段为空

handleSubmitFinalIsa(e) {
    e.preventDefault()

    var formData = new FormData();
    for (const key of Object.keys(this.state.image)) {
        formData.append('image', this.state.image[key])
    }
    formData.set("shortDescription", this.state.shortDescription);
    formData.set("areaName",this.state.areaName);
    formData.set("description",this.state.description);
    formData.set("price",this.state.price);
    axios.post("https://localhost:3886/appartments", formData, {
    }).then(res => {
        console.log(res.data)
    })
  }

EDIT2:第一次编辑后,我意识到我没有跟踪刚刚添加 onChange 的输入文件更改,最后它起作用了

标签: reactjsexpressfrontendfetchbackend

解决方案


推荐阅读