react无法在不刷新页面的情况下两次使用fileinput

时间:2019-03-13 14:42:14

标签: reactjs file-upload

我正在使用html fileinput来通过reactjs上传文件,但是一旦我上传了文件,就不能调用该函数来上传另一个文件,除非我刷新页面。

我的代码的简化版本是:

class Matrice extends React.Component {
  constructor(props) {
    super(props);
    this.fileInput = null;
  }

  uploadQuestion = async e => {
    console.log("uploading question");
    if (e.target.files[0]) {
      const form = new FormData();
      let type;
      if (e.target.files[0].type == "image/jpeg") type = ".jpg";
      if (e.target.files[0].type == "image/png") type = ".png";
      if (e.target.files[0].type == "image/gif") type = ".gif";
      // const fileName = this.props.current + type;
      form.append("files", e.target.files[0]); //filename
      form.append("ref", "exam"); // model
      form.append("refId", this.props.match.params.id); // id
      form.append("field", "media"); // name of field (image field)
      this.setState({ questionUploadLoading: true });
      const files = await strapi.upload(form);
      this.saveMontage(files, undefined, "question");
    }
  };

  render() {
    return (
      <>
        <input
          style={{ display: "none" }}
          ref={fileInput => (this.fileInput = fileInput)}
          onChange={this.uploadQuestion}
          className="file"
          type="file"
          id="imgAdd"
        />
        <button
          onClick={() => this.fileInput.click()}
          type="button"
          className="btn btn-secondary"
        >
          <i className="fas fa-image" />
        </button>
      </>
    );
  }
}

但是,一旦我完成文件的上传,就不能再次调用我的函数uploadQuestion。即,console.log(“上传问题”)没有出现(第二次)。

我不知道可能是什么原因,但是我想是某种原因阻止了onChange处理程序,好像第二次上载文件并没有“更改”触发器。

有人知道是什么原因造成的吗?

谢谢

3 个答案:

答案 0 :(得分:3)

您需要设置要上传的图像的状态,该步骤存在流程

  1. 在构造函数中设置上传文件的状态(uploadFile:null)

  2. 为处理文件更改添加功能

  3. 使用状态upload(uploadFile)到uploadQuestion()而不是e.target.value [0]

  4. 在将setState上载后返回到uploadFile:null

  5. 将文件输入设置为onChange = {this.fileHandle}

class Matrice extends React.Component {
    constructor(props) {
        super(props);
        this.state:{
            uploadFile:null
        }
        this.fileInput = null;
        this.fileHandle = this.fileHandle.bind(this)
    }

fileHandle (e, a) {
    e.preventDefault()
    this.setState({ upload: e.target.files[0] })
  };

uploadQuestion = async (e) => {
    console.log('uploading question')
    if (e.target.files[0]) {
        const form = new FormData();
        let type;
        if (e.target.files[0].type == 'image/jpeg') type = '.jpg'
        if (e.target.files[0].type == 'image/png') type = '.png';
        if (e.target.files[0].type == 'image/gif') type = '.gif';
        // const fileName = this.props.current + type;
        //Use state upload(uploadFile) into uploadQuestion() instead of e.target.value[0]
        file.append('images', this.state.uploadFile, this.state.uploadFile.name) //filename
        form.append('ref', 'exam'); // model
        form.append('refId', this.props.match.params.id) // id
        form.append('field', 'media') // name of field (image field)
        this.setState({questionUploadLoading: true})
        const files = await strapi.upload(form);
        this.saveMontage(files, undefined, 'question')
        //After Upload setState back to uploadFile:null
        this.setState({uploadFile:null})
    }

}

如果您希望在onChange中生效,则可以按以下方式修改功能


fileHandle (e) {
    e.preventDefault()
    if (!e.target.files[0].name.match(/.(jpg|jpeg|png|gif)$/i)) {
      this.setState({ errorMsg: 'Please upload valid file. Allowed format jpg, jpeg, png, gif' })
      return false
    } else {
      this.setState({ upload: e.target.files[0], errorMsg: '' })
    }
  };

答案 1 :(得分:2)

您可以通过将文件input设置为空字符串来重置文件value,然后再次使用它。

uploadQuestion = async (e) => {
    console.log('uploading question')
    if (e.target.files[0]) {
        // ...
        this.fileInput.value = "";
    }
}

答案 2 :(得分:1)

我在这方面玩得很开心,无论我从上面做什么,都没有用。现在,我只是将值硬编码为一个空字符串,我可以一遍又一遍地上传。我什至不确定为什么会这样,但我不需要文本值。服务器很关心这个。这是一个使用 Material-UI 的样式按钮,您永远不会看到输入,但您可以一遍又一遍地上传(在我的情况下,服务器发回一些错误,请修复您的 xlsx 文件消息,我需要用户能够修复和再试一次):

import React from 'react';
import { Button } from '@material-ui/core';
import BackupIcon from '@material-ui/icons/Backup';

const UploadButton = ({ onChange, name, label, disabled }) => {
    return (
        <div className={'MuiFormControl-root MuiTextField-root'}>
            <input
                name={name}
                id='contained-button-file'
                type='file'
                accept='.csv, application/vnd.ms-excel, application/vnd.openxmlformats-officedocument.spreadsheetml.sheet'
                style={{ display: 'none' }}
                onChange={onChange}
                disabled={disabled}
                value=''
            />
            <label htmlFor='contained-button-file'>
                <Button
                    color='primary'
                    aria-label='Upload scan file.'
                    variant='contained'
                    component='span'
                    startIcon={<BackupIcon />}
                    disabled={disabled}
                >
                    {label}
                    </Button>
            </label>
        </div>
    );
};

export default UploadButton;