ReactJS:如何使用Formik处理图像/文件上传?

时间:2019-05-15 12:49:05

标签: reactjs react-redux reducers formik

我正在使用ReactJS为我的网站设计一个个人资料页面。 现在我的问题是如何从本地计算机上载图像并将其保存到数据库中并在配置文件页面中显示

import React, {Component} from 'react';
import { connect } from 'react-redux';
import { AccountAction } from '../../actions/user/AccountPg1Action';
import { Formik, Form, Field, ErrorMessage } from 'formik';
import * as Yup from 'yup';

class AccountInfo extends Component {
  constructor(props) {
    super(props) 
    this.state = {
      currentStep: 1,
      userAccountData: {
        userid: '',
        useravtar: '',
        attachement_id: '',
   }
  }
 }

handleFileUpload = (event) => {
  this.setState({useravtar: event.currentTarget.files[0]})
};

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

handleSubmit = event => {
    let that = this;
    const { AccountAction } = that.props;
    event.preventDefault();

    let accountInputs = {
      userid: 49,
      useravtar: that.state.image,
      attachement_id: 478,
}
    that.setState({
      userAccountData: accountInputs,
    })

    AccountAction(accountInputs)
  }
AccountInfoView = () => {
console.log(this.state.useravtar)
    return (
      <section id="account_sec" className="second_form">
      <div className="container">
      <React.Fragment>
        <Formik
          initialValues={‌{
            file: null,
            email: '',
            phone: ''
          }}
          validationSchema={accountInfoSchema}
          render={(values) => {
          return(
        <Form onSubmit={this.handleSubmit}>
        <Step1 
          currentStep={this.state.currentStep} 
          handleChange={this.handleChange}
          file= {this.state.useravtar}
          handleFileUpload={this.handleFileUpload}
          />
          </Form>
        );
      }}
      />
      </React.Fragment>
      )
  }

  render() {    

    return (
      <div>{this.authView()}</div>
    )
  }
}

function Step1(props) {
console.log(props.useravtar)
  if (props.currentStep !== 1) {
    return null
  } 

  return(
    <div className="upload">
        <label htmlFor="profile">
          <div className="imgbox">
            <img src="images/trans_116X116.png" alt="" />
            <img src={props.useravtar} className="absoImg" alt="" />
          </div>
        </label>
<input id="file" name="file" type="file" accept="image/*" onChange={props.handleFileUpload}/>
        <span className="guide_leb">Add your avatar</span>
      </div>
  )
}

当我在handleChange动作中为event.target.file [0]进行控制台时,它的响应未定义。

另外,在console.log(this.state.useravtar)动作中执行handleSubmit时,它会显示类似c:/fakepath/imgname.jpg的路径名

P.S:我有多种形式,所以我以Step的方式使用它。我正在使用Redux Reducer来存储数据。

我已经引用了this链接,但我的要求看起来不是这样。

2 个答案:

答案 0 :(得分:1)

Formik默认情况下不支持文件上传,但是您可以尝试以下操作

<input id="file" name="file" type="file" onChange={(event) => {
  setFieldValue("file", event.currentTarget.files[0]);
}} />

"file"代表您用来保存文件的密钥

提交后,您可以使用

获取文件的文件名,大小等。
onSubmit={(values) => {
        console.log({ 
              fileName: values.file.name, 
              type: values.file.type,
              size: `${values.file.size} bytes`
            })

如果要将文件设置为组件状态,则可以使用

onChange={(event) => {
  this.setState({"file": event.currentTarget.files[0]})};
}}

根据您的代码,您必须按以下方式处理文件上传

在AccountInfo中添加一个处理文件上传的功能

handleFileUpload = (event) => {
this.setState({WAHTEVETKEYYOUNEED: event.currentTarget.files[0]})};
}

并将相同的函数传递给Step1组件,如下所示

    <Step1 
      currentStep={this.state.currentStep} 
      handleChange={this.handleChange}
      file= {this.state.image}
      handleFileUpload={this.handleFileUpload}
      />

在上传文件的Step1组件中,将输入更改为

<input id="file" name="file" type="file" accept="image/*" onChange={props.handleFileUpload}/>

如果您需要预览上传的图片,则可以创建一个Blob,并将其与图片来源相同,如下所示

<img src={URL.createObjectURL(FILE_OBJECT)} /> 

答案 1 :(得分:0)

您可以使用 Formik 上传带有验证的单个或多个文件,如下所示:

@SecurityRequirement(name = "access_token")

注意:您可以根据需要自定义 min(您的选择,“您的消息”)

import "./App.css";
import { useEffect, useState } from "react";
import * as Yup from "yup";
import { Formik, Field, Form, ErrorMessage, useField } from "formik";
import axios from "axios";


function App() {
  return (
    <Formik
      initialValues={{
        profile: [],
      }}
      validationSchema={Yup.object({
        profile:Yup.array().min(1,"select at least 1 file")
      })}
      onSubmit={(values, props) => {
        let data = new FormData();
        values.profile.forEach((photo, index) => {
          data.append(`photo${index}`, values.profile[index]);
        });
        axios
          .post("you_api_for_file_upload", data, {
            headers: {
              "Content-Type": "multipart/form-data",
            },
          })
          .then((response) => {
            console.log(response);
          })
          .catch((err) => {
            console.log(err);
          });
      }}
    >
      {(formik) => {
        return (
          <>
            <Form>
              <input
                id="file"
                name="profile"
                type="file"
                onChange={(event) => {
                  const files = event.target.files;
                  let myFiles =Array.from(files);
                  formik.setFieldValue("profile", myFiles);
                }}
                multiple
              />
              <ErrorMessage name="profile"/>
              <button type="submit" disabled={formik.isSubmitting}>
                Submit
              </button>
            </Form>
          </>
        );
      }}
    </Formik>
  );
}

export default App;