Загружать изображения вместе с другими текстовыми вводами в React? - PullRequest
0 голосов
/ 28 октября 2019

Очень странно, что все учебники, которые я нашел в Интернете, показывают, как загрузить изображение, но не показывают, как это сделать с другими включенными текстовыми вводами.

Таким образом, я столкнулся с проблемой, пытаясь загрузить изображения, а также другие текстовые данные в той же форме. Потратил часы на поиск в SO и Google, но не смог найти ничего подходящего для моей ситуации.

Я использую React & Redux и пакет express-fileupload для загрузки файлов.

В любом случаевот что я пробовал:

Backend

campgroundRoutes.js

const express = require('express');
const router = express.Router();
const fileUpload = require('express-fileupload');
router.use(fileUpload());

const Campground = require(`../../models/campground`);
const checkAuth = require('../../middleware/check-auth');


router.post('/', checkAuth, (req, res, next) => {

  const file = req.files.file;
  console.log('req.files: ', req.files); // req.files is undefined

  uploadPath = './assets/uploadedImages/' + file.name;

  file.mv(uploadPath, err => {
    if (err) {
      console.error('Error: ', err);
      return res
        .status(500)
        .json({ error: err, message: 'Failed to upload file' });
    }
    res.json({ fileName: file.name });
  });

  const campgroundToPost = new Campground({
    title: req.body.title,
    description: req.body.description,
    cost: req.body.cost,
    imageName: file.name,
    _author: {
      id: req.userData.userId,
      firstName: req.userData.firstName
    }
  });
  campgroundToPost
    .save()
    .then(result => res.status(200).json({ campground: result }))
    .catch(err => res.status(400).send(`Failed to add campground, ${err}`));
});

Внешний интерфейс

addCampground.js

import React, { Component } from 'react';
import TextField from '@material-ui/core/TextField';
import Card from '@material-ui/core/Card';
import CardContent from '@material-ui/core/CardContent';
import Typography from '@material-ui/core/Typography';

import Button from '@material-ui/core/Button';
import '../../styles/addCampground.css';

import { connect } from 'react-redux';
import { bindActionCreators } from 'redux';

import {
  actionAddCampground,
  getCampgroundDetails
} from './actions/campgroundActions';

class AddCampground extends Component {
  constructor(props) {
    super(props);
    this.state = {
      title: '',
      description: '',
      cost: '',
      selectedImage: null
    };
  }

  handleChange = e => {
    const { name, value } = e.target;
    this.setState({
      [name]: value
    });
  };

  uploadImage = e => {
    this.setState(
      {
        selectedImage: e.target.files[0]
      },
      () => console.log(this.state.selectedImage)
    );
  };

  addCampground = () => {
    const title = this.state.title;
    const description = this.state.description;
    const cost = this.state.cost;
    const data = new FormData();
    data.append('file', this.state.selectedImage);
    this.props
      .actionAddCampground({
        title,
        description,
        cost,
        data
      })
      .then(res => console.log(res))
      .catch(err => console.log('Error: ', err));
    this.props.history.push('/home');
  };

  render() {
    return (
        <Card className="add-campground-card">
          <CardContent>
            <Typography
              style={{ fontWeight: '400' }}
              className="text-center"
              variant="h6"
              component="h6">
              Add Your Campground
            </Typography>
          </CardContent>
          <TextField
            autoComplete="off"
            name="title"
            className="textfield"
            label="Campground name"
            variant="outlined"
            value={this.state.title}
            onChange={e => this.handleChange(e)}
          />
          <TextField
            autoComplete="off"
            name="description"
            className="textfield"
            label="Campground description"
            variant="outlined"
            value={this.state.description}
            onChange={e => this.handleChange(e)}
          />
          <TextField
            autoComplete="off"
            name="cost"
            className="textfield"
            type="number"
            label="Campground cost"
            variant="outlined"
            value={this.state.cost}
            onChange={e => this.handleChange(e)}
          />  
          <input onChange={this.uploadImage} type="file" name="file" />
          <Button
            className="add-campground"
            variant="contained"
            color="primary"
            onClick={this.addCampground}>
            Add Campground
          </Button>
        </Card>
    );
  }
}

const mapStateToProps = state => {
  return {
    campground: state.campgroundList.singleCampground
  };
};

const mapDispatchToProps = dispatch => {
  return bindActionCreators(
    {
      actionAddCampground,
      getCampgroundDetails
    },
    dispatch
  );
};

export default connect(
  mapStateToProps,
  mapDispatchToProps
)(AddCampground);

campgroundActions.js

// Only including add campground action here as only that's relevant

import {
  ADD_CAMPGROUND,
} from '../actionTypes/types';

import axios from 'axios';
import { authHeader } from '../../../helpers/auth-header';

const API_URL = `http://localhost:5000/api`;

export const actionAddCampground = campground => {
  return async dispatch => {
    try {
      const res = await axios.post(`${API_URL}/campgrounds`, campground, {
        headers: authHeader()
      });
      dispatch({
        type: ADD_CAMPGROUND,
        payload: res
      });
      return res.data;
    } catch (err) {
      return console.log(err);
    }
  };
}; 

authHeader.js

export const authHeader = () => {
  let user = JSON.parse(localStorage.getItem('user'));
  let token = localStorage.getItem('token');
  if (user && token) {
    return {
      Authorization: token
    };
  } else {
    return {};
  }
};

Это ошибка, которую я получаю в бэкэнде:

TypeError: Cannot read property 'file' of undefined

Я не могувыяснить, где я иду не так.

1 Ответ

0 голосов
/ 28 октября 2019

Несколько дней назад Даже я столкнулся с той же проблемой, когда мне приходилось отправлять файл и другое поле ввода. В конце концов, этот код помог мне при вызове API посмотреть, поможет ли это вам

//-------------To insert Documents and InputField--------------//

export function documentsInsert( documentName, document ) {

var formData = new FormData();
formData.append("documentName", documentName)
formData.append("document", document)

return request2({
    url: xyzzz,
    method: 'POST',
    body: formData
});
}
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...