React使用rc-upload進(jìn)行文件上傳

1. 安裝npm i rc-upload(官網(wǎng)https://www.npmjs.com/package/rc-upload)
2. 使用

引入import RcUpload from 'rc-upload'

interface FileUploadProps {
  name?: string // 上傳的字段文件名
  action?: string // 上傳的路徑
  className?: string // 樣式類名
  style?: object // 行內(nèi)樣式
  multiple?:boolean // 是否多選
  accept?:string // 允許上傳的類型
  size?:number // 限制的大小
  params?: any // 上傳的時(shí)候的參數(shù)
  successChange?: Function // 成功之后
  mobxGlobal?: any
}

interface FileUploadState {
  accept: string
  fileSize: number
  filename: string
  errmsg: string
  errurl: string
  visible: boolean
  progressPercent: number
}

@inject('mobxGlobal')
export default class FileUpload extends RootComponent<FileUploadProps, FileUploadState> {
  basicModel: React.RefObject<BasicModal>

  constructor (props:any) {
    super(props)
    const { accept, size, name } = this.props
    this.state = {
      accept: accept || '.xlsx,.xls', // '.xlsx,.xls'
      fileSize: size || 10,
      filename: name || 'file',
      errmsg: '',
      errurl: '',
      visible: false,
      progressPercent: 0
    }
    this.basicModel = React.createRef()
  }

  /**
   * 組件銷毀之前 對(duì) state 的狀態(tài)做出處理
   */
  componentWillUnmount () {
    this.setState = (state, callback) => {}
  }

  // 開始上傳文件:實(shí)際不會(huì)進(jìn)行上傳的
  onStart = (file:any) => {
    // 文件開始上傳
  }

  onProgress = (file:any) => {
    // console.log(file)
  }

  /** 導(dǎo)出之后的下載 */
  showModel = (url:string, msg:string) => {
    this.setState({
      errmsg: msg,
      errurl: url
    })
    this.handleModal(1) // 正常導(dǎo)入的錯(cuò)誤的信息
  }

  onSuccess = (res: any, file: any) => {
    let { successChange } = this.props
    if (successChange) {
      successChange(res)
    } else {
      const { errNum, errMessage, excelUrl, successNum } = res.data
      if (errNum > 0) {
        this.showModel(excelUrl, errMessage)
      } else if (errNum < 1 && successNum > 0) {
        this.$message.success('導(dǎo)入成功!')
      } else {
        this.$message.error('導(dǎo)入失??!')
      }
    }
  }

  onError = (err:any, flg:boolean) => {
    const { code, msg } = err
    this.error(msg || err)
    // if (flg) {
    //   if (code === 401) {
    //     this.error(msg)
    //   } else {
    //     this.error('文件格式不正確!')
    //   }
    // } else {
    //   this.error(err)
    // }
  }

  /* 文件上傳的 檢查 */
  beforeUpload = (file:any, fileList:any) => {
    const { accept, fileSize } = this.state
    const { size, name } = file
    let a = '文件上傳出錯(cuò)'
    return new Promise((resolve, reject) => {
      // 對(duì)文件的信息進(jìn)行 類型判斷
      let index = name.lastIndexOf('.')
      let typeArry = accept.split(',')
      let suffer = (name as string).substring(index, name.length)
      if (typeArry.indexOf(suffer) < 0) {
        a = '請(qǐng)上傳正確的文件'
        this.$message.error(a)
        reject(a)
      }
      if ((size / 1024 / 1024) > fileSize) { // 對(duì)文件進(jìn)行 大小判斷
        a = `上傳文件的大小不能超過(guò)${fileSize}M`
        this.$message.warning(a)
        reject(a)
      }
      resolve(file)
    })
  }

  // /* 自定義的文件上傳, 默認(rèn)的不傳,直接成功 */
  // customRequest = (request:any) => {
  //   const { action, file, filename, fileSize, data, onProgress, onSuccess, onError } = request
  //   let formData = new FormData()
  //   let params = this.props.params
  //   // 創(chuàng)建對(duì)象的信息
  //   formData.append(filename, file, file.name)
  //   if (params) {
  //     for (const key in params) {
  //       formData.append(key, params[key])
  //     }
  //   }
  //   this.setState({ visible: true, progressPercent: 0 })
  //   let time:any = setInterval(() => {
  //     let { progressPercent } = this.state
  //     if (progressPercent >= 80) {
  //       clearInterval(time)
  //     } else {
  //       progressPercent += 8
  //     }
  //     this.setState({ progressPercent })
  //   }, 1000)
  //   this.axios.upload({
  //     method: 'post',
  //     url: action,
  //     data: formData
  //     // onUploadProgress: (progressEvent:any) => {
  //     //   if (progressEvent.lengthComputable) {
  //     //     this.onUploadProgressLoading(progressEvent)
  //     //   }
  //     // }
  //   }).then((res:any) => {
  //     const { code, data, msg } = res.data
  //     if (code === 200) {
  //       onSuccess(res.data, file)
  //     } else {
  //       onError(res.data, true)
  //     }
  //   }).catch((err:any) => {
  //     onError(err, false)
  //   }).finally(() => {
  //     this.setState({ visible: false, progressPercent: 100 })
  //   })
  // }

  /* 自定義的文件上傳, 默認(rèn)的不傳,直接成功 */
  customRequest = (request:any) => {
    const { action, file, filename, fileSize, data, onProgress, onSuccess, onError } = request
    const { mobxGlobal: { setTaskNum } } = this.props
    let formData = new FormData()
    let params = this.props.params
    // 創(chuàng)建對(duì)象的信息
    formData.append(filename, file, file.name)
    if (params) {
      for (const key in params) {
        formData.append(key, params[key])
      }
    }
    this.axios.upload({
      method: 'post',
      url: action,
      data: formData
    }).then((res:any) => {
      let { data, code, msg } = res.data
      if (code === 200) {
        this.warning('數(shù)據(jù)正在導(dǎo)入中,請(qǐng)至任務(wù)管理查看報(bào)表!')
        this.axios.request(this.api.count).then(({ code, data }) => {
          if (code === 200) {
            let { sun } = data
            sun = sun > 99 ? '99+' : sun
            this.props.mobxGlobal.setTaskNum(sun)
          }
        })
      } else {
        this.warning(`${msg[0]}`)
      }
    }).finally(() => {
      this.setState({ visible: false, progressPercent: 100 })
    })
  }

  /* 打開彈窗: 錯(cuò)誤的小消息存在 */
  handleModal = (num: number = 0) => {
    const { handleOk, handleCancel } = this.basicModel.current as BasicModal
    num === 0 ? handleCancel() : handleOk()
  }

  /** 下載數(shù)據(jù) */
  dowloadFile = (url:string) => {
    let link = document.createElement('a')
    link.style.display = 'none'
    link.href = url
    document.body.appendChild(link)
    link.click()
    this.handleModal(0)
    this.$message.success('下載成功!')
  }

  /** 上傳的進(jìn)度 */
  // onUploadProgressLoading = ({ total, loaded }:any) => {
  //   let progressPercent:number = (total / loaded) * 100
  //   let visible:boolean = true
  //   this.setState({ visible, progressPercent })
  // }

  render () {
    const { multiple, action, name, style } = this.props
    const { filename, accept, errmsg, errurl, visible, progressPercent } = this.state
    const config = {
      action: action,
      name: filename,
      accept: accept, // 默認(rèn)上傳的是圖片
      multiple: multiple, // 多選
      onStart: this.onStart, // 開始上傳文件
      onProgress: this.onProgress, // 進(jìn)度回調(diào),僅適用于現(xiàn)代瀏覽器
      onSuccess: this.onSuccess, // 成功回調(diào)
      onError: this.onError, // 錯(cuò)誤回調(diào)
      beforeUpload: this.beforeUpload, // 上傳前的驗(yàn)證
      customRequest: this.customRequest // 提供默認(rèn)xhr行為的替代以進(jìn)行其他自定義
    }
    return (
      <div className="upload-file-content" style={style}>
        <RcUpload {...config}>
          {this.props.children}
        </RcUpload>
        <Modal title="" closable={false} footer={null} visible={visible}>
          <div className="upload-progress">
            <p>正在導(dǎo)入,請(qǐng)稍等...</p>
            <Progress strokeColor={{
              to: '#24C8EA',
              from: '#2B8FF9'
            }}
            status="active" percent={progressPercent} />
          </div>
        </Modal>
        <BasicModal ref={this.basicModel} title="提示">
          <Row>
            <Col span={7} style={{ textAlign: 'center' }}><img src={js}></img></Col>
            <Col span={17} className="error-col">{errmsg}</Col>
          </Row>
          <Row>
            <div className="import-error">
              <p>出錯(cuò)原因可能為:</p>
              <p>1.數(shù)據(jù)不完整(必填項(xiàng)為空);</p>
              <p>2.字段格式不正確(如導(dǎo)入數(shù)據(jù)中的“項(xiàng)目”為系統(tǒng)內(nèi)沒(méi)有的項(xiàng)目名稱等);</p>
              <p>3.與原數(shù)據(jù)沖突(如導(dǎo)入的員工相關(guān)記錄在系統(tǒng)中已存在)。</p>
            </div>
          </Row>
          <Row>
            <Button type="primary" onClick={() => (this.dowloadFile(errurl))}>下載出錯(cuò)數(shù)據(jù)</Button>
          </Row>
        </BasicModal>
      </div>
    )
  }
}

該文件主要用于后臺(tái)管理系統(tǒng)的導(dǎo)入功能

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時(shí)請(qǐng)結(jié)合常識(shí)與多方信息審慎甄別。
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡(jiǎn)書系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。

友情鏈接更多精彩內(nèi)容