king
2023-12-01 7a6874905fa9c6cec03040b29c455db7e81fb22e
src/tabviews/zshare/fileupload/index.jsx
@@ -2,22 +2,19 @@
import PropTypes from 'prop-types'
import { is, fromJS } from 'immutable'
import moment from 'moment'
import { Upload, Button, Icon, Progress, notification } from 'antd'
import { Upload, Button, Progress, notification } from 'antd'
import { UploadOutlined } from '@ant-design/icons'
import SparkMD5 from 'spark-md5'
import Api from '@/api'
import './index.scss'
let service = ''
if (process.env.NODE_ENV === 'production') {
  service = document.location.origin + '/' + window.GLOB.service
} else {
  service = window.GLOB.location + '/' + window.GLOB.service
}
import Api from '@/api'
import MKEmitter from '@/utils/events.js'
import './index.scss'
class FileUpload extends Component {
  static propTpyes = {
    config: PropTypes.object,  // 表单信息
    onChange: PropTypes.func,  // 表单变化
    data: PropTypes.any,
    config: PropTypes.object,
    onChange: PropTypes.func,
  }
  state = {
@@ -27,42 +24,67 @@
    maxFile: null,
    rduri: '',
    limit: 2,
    compress: false,
    compress: 'false',
    fileType: 'text',
    showprogress: false,
    maxSize: 0,
    filelist: []
  }
  UNSAFE_componentWillMount () {
    const { config } = this.props
    const { config, data } = this.props
    let filelist = []
    if (config.initval) {
      try {
        filelist = config.initval.split(',').map((url, index) => {
          return {
            uid: `${index}`,
            name: url.slice(url.lastIndexOf('/') + 1),
            status: 'done',
            url: url,
            origin: true
      if (/^data:image/.test(config.initval)) {
        filelist = [{
          uid: '0',
          name: 'data:image/jpeg;base64',
          status: 'done',
          url: config.initval,
          origin: true
        }]
      } else {
        try {
          filelist = config.initval.split(',').map((url, index) => {
            return {
              uid: `${index}`,
              name: url.slice(url.lastIndexOf('/') + 1),
              status: 'done',
              url: url,
              origin: true
            }
          })
        } catch (e) {
          filelist = []
        }
        if (data && config.subFields && config.subFields.length === 1 && filelist.length === 1) {
          if (data[config.subFields[0].field]) {
            filelist[0].name = data[config.subFields[0].field]
          }
        })
      } catch (e) {
        filelist = []
        }
      }
    }
    let accept = ''
    let accepts = null
    let compress = false
    if (config.compress === 'true') {
      compress = true
    let compress = config.compress || 'false'
    let maxFile = config.maxfile && config.maxfile > 0 ? config.maxfile : null
    if (compress === 'true' || compress === 'base64') {
      accepts = ['.jpg', '.png', '.gif', '.jpeg']
      accept = accepts.join(',')
      if (compress === 'base64') {
        maxFile = 1
      }
    } else if (config.suffix) {
      accepts = config.suffix.split(',')
      accept = config.suffix
      accepts = config.suffix.split(',').map(item => {
        if (!/^\./ig.test(item)) {
          item = '.' + item
        }
        return item
      })
      accept = accepts.join(',')
    }
    let rduri = config.rduri || ''
    
@@ -77,7 +99,8 @@
      filelist,
      compress,
      limit: config.limit || 2,
      maxFile: config.maxfile && config.maxfile > 0 ? config.maxfile : null,
      maxSize: config.maxSize || 0,
      maxFile: maxFile,
      fileType: config.fileType || 'text'
    })
  }
@@ -115,7 +138,9 @@
    this.props.onChange(vals.join(','))
  }
  onUpdate = (url) => {
  onUpdate = (url, file_name) => {
    const { config } = this.props
    let filelist = fromJS(this.state.filelist).toJS()
    if (filelist[filelist.length -1]) {
@@ -137,7 +162,20 @@
    })
    this.setState({filelist})
    this.props.onChange(vals.join(','))
    if (config.subFields && file_name) {
      let other = {}
      config.subFields.forEach((n, i) => {
        other[n.field] = file_name
        setTimeout(() => {
          MKEmitter.emit('mkFC', 'input', n.uuid, file_name)
        }, i * 5)
      })
      this.props.onChange(vals.join(','), other)
    } else {
      this.props.onChange(vals.join(','))
    }
  }
  onFail = (msg) => {
@@ -157,46 +195,38 @@
    })
  }
  shardupload = (params) => {
    let param = params.chunks.shift()
  shardupload = (param, file_name) => {
    let form = new FormData()
    form.append('file', param.binary)
    form.append('fileMd5', params.file.fileMd5)
    form.append('shardingMd5', param.chunkMd5)
    form.append('baseDomain', service)
    form.append('fileMd5', param.fileMd5)
    form.append('shardingMd5', param.fileMd5)
    form.append('baseDomain', window.GLOB.baseurl)
    form.append('rootPath', 'Content/images/upload/')
    form.append('fileName', params.file.fileName)
    form.append('fileExt', params.file.fileType)
    form.append('shardingCnt', param.chunks)
    form.append('shardingNo', param.chunk)
    form.append('fileName', param.fileName)
    form.append('fileExt', param.fileType)
    form.append('shardingCnt', 1)
    form.append('shardingNo', 1)
    form.append('LoginUID', sessionStorage.getItem('LoginUID') || '')
    form.append('UserID', sessionStorage.getItem('UserID') || '')
    Api.getLargeFileUpload(form).then(res => {
      if (res.status) {
        if (params.chunks.length > 0) {
          this.setState({
            percent: Math.floor(100 * (param.chunk / param.chunks))
          })
          this.shardupload(params)
        if (res.urlPath) {
          this.onUpdate(res.urlPath, file_name)
        } else {
          if (res.urlPath) {
            this.onUpdate(res.urlPath)
          } else {
            this.onFail()
          }
          this.setState({
            percent: 100
          }, () => {
            setTimeout(() => {
              this.setState({
                showprogress: false,
                percent: 0
              })
            }, 200)
          })
          this.onFail()
        }
        this.setState({
          percent: 100
        }, () => {
          setTimeout(() => {
            this.setState({
              showprogress: false,
              percent: 0
            })
          }, 200)
        })
      } else {
        this.onFail(res.message)
      }
@@ -214,7 +244,7 @@
  }
  beforeUpload = (file) => {
    const { accepts, compress, limit, rduri } = this.state
    const { accepts, compress, limit, rduri, maxSize } = this.state
    if (accepts && file.name) {
      let pass = false
@@ -225,12 +255,20 @@
      })
      
      if (!pass) {
        notification.warning({
          top: 92,
          message: '文件格式错误!',
          duration: 5
        })
        return
        setTimeout(() => {
          this.onFail('文件格式错误!')
        }, 10)
        return false
      }
    }
    if (maxSize) {
      let fileSize = file.size / 1024 / 1024
      if (fileSize > maxSize) {
        setTimeout(() => {
          this.onFail(`文件大小不可超过${maxSize}M`)
        }, 10)
        return false
      }
    }
@@ -239,7 +277,9 @@
      percent: 0
    })
    if (compress) {
    let file_name = file.name
    if (compress === 'true' || compress === 'base64') {
      let reader = new FileReader()
      let fileSize = file.size / 1024 / 1024
      let compressRate = 0.9
@@ -277,34 +317,49 @@
          let param = {Base64Img: cvs.toDataURL('image/jpeg', compressRate)}
          if (rduri) {
            param.rduri = rduri
          }
          Api.fileuploadbase64(param).then(result => {
            if (result.status && result.Images) {
              let url = service + result.Images
              if (rduri) {
                url = rduri.replace(/webapi(.*)$/, '') + result.Images
              }
              this.onUpdate(url)
              this.setState({
                percent: 100
              }, () => {
                setTimeout(() => {
                  this.setState({
                    showprogress: false,
                    percent: 0
                  })
                }, 200)
              })
            } else {
              this.onFail(result.message)
          if (this.props.config.compress === 'base64') {
            this.onUpdate(param.Base64Img, file_name)
            this.setState({
              percent: 100
            }, () => {
              setTimeout(() => {
                this.setState({
                  showprogress: false,
                  percent: 0
                })
              }, 200)
            })
          } else {
            if (rduri) {
              param.rduri = rduri
            }
          })
            Api.fileuploadbase64(param).then(result => {
              if (result.status && result.Images) {
                let url = window.GLOB.baseurl + result.Images
                if (rduri) {
                  url = rduri.replace(/webapi(.*)$/, '') + result.Images
                }
                this.onUpdate(url, file_name)
                this.setState({
                  percent: 100
                }, () => {
                  setTimeout(() => {
                    this.setState({
                      showprogress: false,
                      percent: 0
                    })
                  }, 200)
                })
              } else {
                this.onFail(result.message)
              }
            })
          }
        }
        img.onerror = () => {
@@ -320,38 +375,61 @@
      reader.readAsDataURL(file)
      return false
    } else if (compress === 'oss') {
      let _param = new FormData()
      _param.append('multipartFile', file)
      _param.append('userId', sessionStorage.getItem('UserID') || '')
      Api.fileOssUpload(_param).then(res => {
        if (res.status) {
          if (res.urlPath) {
            let path = (/^\/\//.test(res.urlPath) ? 'https:' : '') + res.urlPath
            this.onUpdate(path, file_name)
            this.setState({
              percent: 100
            }, () => {
              setTimeout(() => {
                this.setState({
                  showprogress: false,
                  percent: 0
                })
              }, 200)
            })
          } else {
            this.onFail('文件上传失败!')
          }
        } else {
          this.onFail(res.message || '文件上传失败!')
        }
      })
      return false
    }
    // 兼容性的处理
    let blobSlice = File.prototype.slice || File.prototype.mozSlice || File.prototype.webkitSlice
    let chunkSize = 1024 * 1024 * 2                // 切片每次2M
    let chunks = Math.ceil(file.size / chunkSize)  // 切片总数
    let currentChunk = 0                           // 当前上传的chunk
    let spark = new SparkMD5.ArrayBuffer()         // 对arrayBuffer数据进行md5加密,产生一个md5字符串
    let chunkFileReader = new FileReader()         // 用于计算出每个chunkMd5
    let totalFileReader = new FileReader()         // 用于计算出总文件的fileMd5
    let params = {chunks: [], file: {}}            // 用于上传所有分片的md5信息
    let param = {}
    params.file.fileName = file.name.replace(/\.{1}[^.]*$/ig, '')  // 文件名(去除后缀名)
    params.file.fileType = file.name.replace(/^.*\.{1}/ig, '')     // 文件类型
    params.file.fileSize = file.size                               // 文件大小
    params.file.fileChunks = chunks                                // 记录所有chunks的长度
    param.fileName = file.name.replace(/\.{1}[^.]*$/ig, '')  // 文件名(去除后缀名)
    param.fileType = file.name.replace(/^.*\.{1}/ig, '')     // 文件类型
    if (!/^[A-Za-z0-9]+$/.test(params.file.fileName)) {            // 文件名称含有英文及数字之外字符时,名称系统生成
      params.file.fileName = moment().format('YYYYMMDDHHmmss') + this.getuuid()
    if (!/^[A-Za-z0-9]+$/.test(param.fileName)) {            // 文件名称含有英文及数字之外字符时,名称系统生成
      param.fileName = moment().format('YYYYMMDDHHmmss') + this.getuuid()
    }
    totalFileReader.readAsArrayBuffer(file)
    totalFileReader.onload = (e) => {   // 对整个totalFile生成md5
      spark.append(e.target.result)
      params.file.fileMd5 = spark.end() // 计算整个文件的fileMd5
      param.fileMd5 = spark.end()       // 计算整个文件的fileMd5
      param.binary = file
      let _param = new FormData()
      _param.append('fileMd5', params.file.fileMd5)
      _param.append('fileMd5', param.fileMd5)
      
      Api.getFilePreUpload(_param).then(res => {
        if (res.status && res.urlPath) {
          this.onUpdate(res.urlPath)
          this.onUpdate(res.urlPath, file_name)
          this.setState({
            percent: 100
          }, () => {
@@ -362,54 +440,14 @@
              })
            }, 200)
          })
        } else if (res.shardings && res.shardings.length > 0) {
          res.shardings.forEach(shard => {
            if (shard.shardingNo && parseInt(shard.shardingNo) > currentChunk) {
              currentChunk = parseInt(shard.shardingNo)
            }
          })
          loadNext()
        } else {
          loadNext()
          this.shardupload(param, file_name)
        }
      })
    }
    chunkFileReader.onload = (e) => {
      spark.append(e.target.result)      // 对每一片分片进行md5加密
      params.chunks[params.chunks.length - 1].chunkMd5 = spark.end() // 添加切片md5
      currentChunk++  // 每一次分片onload,currentChunk都需要增加,以便来计算分片的次数
      if (currentChunk < chunks) { // 当前切片总数没有达到总数时
        loadNext()
      } else {
        this.shardupload(params)
      }
    }
    chunkFileReader.onerror = () => {
      this.onFail('文件读取失败!')
    }
    totalFileReader.onerror = () => {
      this.onFail('文件读取失败!')
    }
    let loadNext = () => {
      let start = currentChunk * chunkSize              // 计算分片的起始位置
      let end = Math.min(file.size, start + chunkSize)  // 计算分片的结束位置
      let obj = {                                       // 每一个分片需要包含的信息
        chunk: currentChunk + 1,
        binary: file.slice(start, end),
        start: start,
        end: end,
        chunks
      }
      params.chunks.push(obj)
      chunkFileReader.readAsArrayBuffer(blobSlice.call(file, start, end))
    }
    return false
@@ -451,10 +489,10 @@
    return (
      <Upload {...props}>
        {fileType !== 'picture-card' ? <Button>
          <Icon type="upload" /> 点击上传
          <UploadOutlined /> 点击上传
        </Button> : null}
        {fileType === 'picture-card' ? <span style={{whiteSpace: 'nowrap'}}>
          <Icon type="upload" /> 点击上传
          <UploadOutlined /> 点击上传
        </span> : null}
        {showprogress ? <Progress percent={percent} size="small" /> : null}
      </Upload>