【问题标题】:how to post image in react-redux using formdata and send to nodejs如何使用formdata在react-redux中发布图像并发送到nodejs
【发布时间】:2019-03-20 15:11:35
【问题描述】:

我是 react 新手,我没有看到任何有关使用 formdata (react) 上传图像的文档,而且我也不能在服务器 (nodejs) 上发送图像。如果你们中的任何人有东西,然后在这里发送mern栈图片上传

【问题讨论】:

    标签: node.js reactjs


    【解决方案1】:

    查看我的 git 存储库,其中包含图像上传反应前端和 node.js 服务器,以将图像上传到 AWS S3 存储桶。 https://github.com/ShanikaEdiriweera/image-upload-app

    作为对@Nguyễn Thanh Tú 答案和 repo 中使用的方法(从反应组件调用 http 请求)的补充,这就是您应该如何使用 Redux 和动作创建者(redux-thunk 作为中间件)来处理 API 等副作用/server 调用。

    组件代码:

    import React, { Component } from 'react';
    import { connect } from 'react-redux';
    import { bindActionCreators } from 'redux';
    import * as imageActions from '../actions/imageActions';
    export default class WhatsApp extends Component {
        ...
    
        handleSubmit = e => {
            e.preventDefault();
            if (!this.fileInput.current.files[0]) return;
            let data = new FormData();
            data.append('logo', this.fileInput.current.files[0]);
    
            // calling the action creator
            this.props.imageActions.imageUpload(data);
        };
    
        ...
    }
    
    function mapDispatchToProps(dispatch) {
        return {
            imageActions: bindActionCreators(imageActions, dispatch),
            ...
        };
    }
    
    export default connect(
        mapStateToProps,
        mapDispatchToProps
    )(WhatsApp);
    

    imageActions.js 动作文件:

    import axios from 'axios';
    ...
    export const imageUpload = (data) => {
        return dispatch => {
            return axios.post('http://127.0.0.1:3100/what', data).then(
                // here we can dispatch redux actions
                // and then handle them in redux reducers
                res => console.log(res.data),
                err => console.log(err.message)
            );
        };
    };
    

    在动作创建器中,我们可以调度redux actions,然后在redux reducers中处理调度的动作,以在前端组件上创建效果。

    【讨论】:

      【解决方案2】:

      如果你对 hooks 和 redux 有反应,这就是我使用和工作的方式。

      诀窍是使用 formData.set(),我之前使用过 formData.append 并且不起作用,将表单字段的状态值发送到 axios.post (我使用 axios.create)。

      如果不需要用户认证,就不需要配置headers。

      很重要!!!,图像字段,将是type='file',并且在状态下使用e.target.files[0]

      在表单组件中:

      //* AQUI ESTARÁ EL FORMULARIO PARA EL PRODUCTO
      import styled from "styled-components";
      import { useState } from "react";
      import Select from "react-select";
      import FormData from "form-data";
      import { useDispatch } from "react-redux";
      import "react-toastify/dist/ReactToastify.css";
      
      //ACTIONS DE REDUX
      import { crearNuevoProductoAction } from "../actions/productoActions";
      
      
      const Label = styled.label`
        font-family: Anton;
      `;
      
      const TextArea = styled.textarea`
        font-family: Lato;
      `;
      
      const tablas = [
        { value: "slalom", label: "Slalom" },
        { value: "freeride", label: "Free-Ride" },
        { value: "freerace", label: "Free-Race" },
        { value: "freestyle", label: "Free-Style" },
        { value: "waves", label: "Waves" },
      ];
      
      const velas = [
        { value: "slalom", label: "Slalom_V" },
        { value: "freeride", label: "Free-Ride" },
        { value: "freerace", label: "Free-Race" },
        { value: "freestyle", label: "Free-Style" },
        { value: "waves", label: "Waves" },
      ];
      
      const botavaras = [
        { value: "carbono", label: "Carbono" },
        { value: "aluminio", label: "Aluminio" },
        { value: "mixtas", label: "Mixtas" },
      ];
      
      const mastiles = [
        { value: "rdm", label: "RDM" },
        { value: "sdm", label: "SDM" },
      ];
      
      const accesorios = [
        { value: "arnes", label: "Arnes" },
        { value: "alargador", label: "Alargador" },
        { value: "aleta", label: "Aleta" },
      ];
      
      const NuevoProducto = () => {
        //MANEJO DE STATES LOCALES
        const [categoria, setCategoria] = useState("");
      
        const handleProduct = (e) => {
          setCategoria(e.target.value);
        };
      
        const [subCategoria, setSubCategoria] = useState("");
      
        const handleSubProduct = (e) => {
          setSubCategoria(e.value);
        };
      
        const [title, setTitle] = useState("");
        const [price, setPrice] = useState("");
        const [description, setDescription] = useState("");
        const [images, setImage] = useState("");
        
        console.log(images)
      
        let subopcion;
      
        switch (categoria) {
          case "tabla":
            subopcion = tablas;
            break;
      
          case "vela":
            subopcion = velas;
            break;
      
          case "botavara":
            subopcion = botavaras;
            break;
      
          case "mastil":
            subopcion = mastiles;
            break;
      
          case "accesorio":
            subopcion = accesorios;
            break;
      
          default:
            subopcion = tablas;
            break;
        }
      
        //MANEJO DEL REDUX EN EL FORMULARIO
      
        //UTILIZAR USEDISPATCH Y TE CREA UNA FUNCION
        const dispatch = useDispatch();
      
        //manda llamar al action de productoAction
        const agregarProducto = (producto) =>
          dispatch(crearNuevoProductoAction(producto));
      
        //AL HACER SUBMIT EN EL FORMULARIO
        
        
        const submitNuevoProducto = (e) => {
          e.preventDefault();
      
          let formData = new FormData();
          formData.set('images', images)
          formData.set('title', title)
          formData.set('categoria', categoria)
          formData.set('subCategoria', subCategoria)
          formData.set('price', price)
          formData.set('description', description)
      
           agregarProducto(formData)
        
        };
      
        return (
          <div className="container mt-5">
            <div className="row justify-content-center">
              <div className="col-md-8">
                <div className="card">
                  <div className="card-body">
                    <h2 className="text-center mx-auto font-wight-bold mb-5">
                      Agregar Nuevo Producto
                    </h2>
                    <form onSubmit={submitNuevoProducto}>
                      <div className="mb-3">
                        <Label className="mb-2">Selecciona el tipo de producto</Label>
                        <select
                          className="custom-select form-control"
                          defaultValue=""
                          name="categoria"
                          onChange={handleProduct}
                        >
                          <option value="" selected>
                            Selecciona el tipo de producto
                          </option>
                          <option value="tabla">Tabla</option>
                          <option value="vela">Vela</option>
                          <option value="botavara">Botavara</option>
                          <option value="mastil">Mastil</option>
                          <option value="accesorio">Accesorio</option>
                        </select>
                      </div>
                      <div className="mb-3">
                        <Label className="mb-2">Selecciona el tipo de producto</Label>
                        <Select
                          defaultValue=""
                          name="subCategoria"
                          onChange={handleSubProduct}
                          options={subopcion}
                        />
                      </div>
                      <div className="mb-3">
                        <Label htmlFor="tituloProducto" className="form-label">
                          Producto
                        </Label>
                        <input
                          type="text"
                          className="form-control"
                          name="title"
                          id="title"
                          placeholder="Tabla Slalom ...."
                          onChange={(e) => setTitle(e.target.value)}
                        ></input>
                      </div>
                      <div className="mb-3">
                        <Label htmlFor="precioProducto" className="form-label">
                          Precio
                        </Label>
                        <input
                          type="number"
                          className="form-control"
                          id="precioProducto"
                          placeholder="450"
                          name="price"
                          onChange={(e) => setPrice(Number(e.target.value))}
                        ></input>
                       
                      </div>
      
                      <div className="mb-3">
                        <Label htmlFor="descripcionProducto" className="form-label">
                          Descripción del Producto
                        </Label>
                        <TextArea
                          className="form-control"
                          id="descripcionProducto"
                          rows="3"
                          onChange={(e) => setDescription(e.target.value)}
                        ></TextArea>
                      </div>
                      <div>
                        <input
                          className="form-input"
                          id="images"
                          type='file'
                          name="images"                                      
                          onChange={(e) => setImage(e.target.files[0])}
                        ></input>
                         
                      </div>
                      <div className="mb-3 text-center">
                        <button className="btn btn-success" type="submit">
                          Agregar Producto
                        </button>
                      </div>
                    </form>
                  </div>
                </div>
              </div>
            </div>
          </div>
        );
      };
      
      export default NuevoProducto;
      

      在 actions.js 中

      import clienteAxios from "../config/axios";
      
      import Swal from 'sweetalert2';
      import FormData from "form-data";
      
      
      const user = JSON.parse(localStorage.getItem('user'));
      const data = ({
        
        headers: {
          'x-auth-token': user,
        },
        //body: {imagenData},
        
      })
      
      console.log(user)
      ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
      //CREAR NUEVOS PRODUCTOS
      export function crearNuevoProductoAction(producto) {
        console.log(producto)
        return async (dispatch) => {   
          dispatch(agregarProducto());
          try {
            //INSERTAR EN LA API
             await clienteAxios.post("/api/productos", producto, data);
            //console.log(respuestaPost.data);
            //SI TODO VA BIEN, SE ACTUALIZA EL STATE
            dispatch(agregarProductoExito(producto));     
            //PONER AQUÍ LA ALERTA DE QUE SE CREO BIEN EL PRODUCTO
            Swal.fire(
              'Correcto',
              'El Producto se subió Correctamente',
              'success'
            ).then(function() {
              window.location = "/productos"})
            
            console.log(producto)
          } catch (error) {
            console.log(error);
            dispatch(agregarProductoError(true));
          }
        };
      }
      
        const agregarProducto = () => ({
        type: AGREGAR_PRODUCTO,
        payload: true,
       });
      
       //SI EL PRODUCTO SE GUARDA EN LA BBDD
        const agregarProductoExito = (producto) => ({
        type: AGREGAR_PRODUCTO_EXITO,
        payload: producto,
        });
      
        //SI HUBO UN ERROR CON EL PRODUCTO
        const agregarProductoError = (estado) => ({
        type: AGREGAR_PRODUCTO_ERROR,
        payload: estado,
         });
      

      【讨论】:

        猜你喜欢
        • 2021-02-04
        • 2021-06-09
        • 1970-01-01
        • 2018-09-12
        • 2016-04-19
        • 1970-01-01
        • 2016-03-28
        • 2021-08-14
        • 1970-01-01
        相关资源
        最近更新 更多