king
2020-06-28 48a18736c461ad730bd264b0ac7b40b68a0e33a1
src/tabviews/zshare/fileupload/index.jsx
@@ -1,13 +1,21 @@
import React, {Component} from 'react'
import PropTypes from 'prop-types'
import { Upload, message, Button, Icon, Progress, notification } from 'antd'
import md5 from 'md5'
import { fromJS } from 'immutable'
import { Upload, Button, Icon, Progress, notification } from 'antd'
import SparkMD5 from 'spark-md5'
import Api from '@/api'
import './index.scss'
let Url = '/Upload'
if (process.env.NODE_ENV === 'production') {
  Url = document.location.origin + '/' + window.GLOB.service + 'zh-CN/Home/Upload'
}
let service = ''
if (process.env.NODE_ENV === 'production') {
  service = document.location.origin + '/' + window.GLOB.service
} else {
  service = window.GLOB.location + window.GLOB.service
}
class FileUpload extends Component {
@@ -21,18 +29,6 @@
    baseUrl: Url,
    percent: 0,
    showprogress: false
  }
  init = async () => {
    try {
      const OSSData = await this.mockGetOSSData()
      this.setState({
        OSSData
      })
    } catch (error) {
      message.error(error)
    }
  }
  onChange = ({ fileList }) => {
@@ -53,89 +49,180 @@
    }
  }
  onUpdate = (url) => {
    const { value, onChange } = this.props
    let filelist = fromJS(value).toJS()
    filelist[filelist.length -1].status = 'done'
    filelist[filelist.length -1].response = url
    filelist[filelist.length -1].origin = false
    if (onChange) {
      onChange([...filelist])
    }
  }
  onDelete = (msg) => {
    const { value, onChange } = this.props
    let filelist = value.filter(v => !v.url && !v.response)
    if (onChange) {
      onChange([...filelist])
    }
    this.setState({
      showprogress: false
    })
    notification.warning({
      top: 92,
      message: msg || '文件上传失败!',
      duration: 5
    })
  }
  getExtraData = () => {
    return {
      RootPath: 'Content/images/upload/'
    }
  }
  shardupload = (file, shardSize, shardCount, i, fileList) => {
    let start = i * shardSize
    let end = Math.min(file.size, start + shardSize)
    // let param = {
    //   file: file.slice(start, end),
    //   fileMd5: md5(''),
    //   shardingMd5: md5(''),
    //   baseDomain: '',
    //   rootPath: 'Content/images/upload/',
    //   fileName: file.name,
    //   fileExt: file.type.replace('image/', ''),
    //   shardingCnt: shardCount,
    //   shardingNo: i + 1
    // }
  shardupload = (params) => {
    let param = params.chunks.shift()
    let form = new FormData()
    let pice = file.slice(start, end)
    form.append('file', pice) //slice方法用于切出文件的一部分
    form.append('fileMd5', md5(file))
    form.append('shardingMd5', md5(pice))
    form.append('baseDomain', '')
    form.append('file', param.binary)
    form.append('fileMd5', params.file.fileMd5)
    form.append('shardingMd5', param.chunkMd5)
    form.append('baseDomain', service)
    form.append('rootPath', 'Content/images/upload/')
    form.append('fileName', file.name)
    form.append('fileExt', file.type.replace('image/', ''))
    form.append('shardingCnt', shardCount)
    form.append('shardingNo', i + 1)
    form.append('fileName', params.file.fileName)
    form.append('fileExt', params.file.fileType)
    form.append('shardingCnt', param.chunks)
    form.append('shardingNo', param.chunk)
    Api.getLargeFileUpload(form).then(res => {
      if (res.status) {
        if (i < shardCount) {
          i++
        if (params.chunks.length > 0) {
          this.setState({
            percent: Math.floor(100 * (i / shardCount))
            percent: Math.floor(100 * (param.chunk / param.chunks))
          })
          this.shardupload(file, shardSize, shardCount, i, fileList)
          this.shardupload(params)
        } else {
          if (res.urlPath) {
            this.onUpdate(res.urlPath)
          } else {
            this.onDelete()
          }
          this.setState({
            percent: 100
          }, () => {
            setTimeout(() => {
              this.setState({
                showprogress: false,
                percent: 0
              })
            }, 200)
          })
        }
      } else {
        fileList = fileList.filter(item => !!item.url)
        notification.warning({
          top: 92,
          message: res.message,
          duration: 5
        })
        this.onDelete(res.message)
      }
    })
    // } else {
    //   this.setState({
    //     percent: 100
    //   }, () => {
    //     setTimeout(() => {
    //       this.setState({
    //         showprogress: false,
    //         percent: 0
    //       })
    //     }, 200)
    //   })
    // }
  }
  beforeUpload = (file, fileList) => {
    let shardSize = 2 * 1024 * 1024
  beforeUpload = (file) => {
    this.setState({
      showprogress: true,
      percent: 0
    })
    if (file.size > shardSize) {
      // this.setState({
      //   showprogress: true,
      //   percent: 0
      // })
      // let shardCount = Math.ceil(file.size / shardSize)
    // 兼容性的处理
    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信息
      // this.shardupload(file, shardSize, shardCount, 0, fileList)
      // return false
      return true
    } else {
      return true
    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的长度
    totalFileReader.readAsArrayBuffer(file)
    totalFileReader.onload = (e) => {   // 对整个totalFile生成md5
      spark.append(e.target.result)
      params.file.fileMd5 = spark.end() // 计算整个文件的fileMd5
      Api.getFilePreUpload({fileMd5: params.file.fileMd5}).then(res => {
        if (res.status && res.urlPath) {
          this.onUpdate(res.urlPath)
          this.setState({
            percent: 100
          }, () => {
            setTimeout(() => {
              this.setState({
                showprogress: false,
                percent: 0
              })
            }, 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()
        }
      })
    }
    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.onDelete()
      console.warn('File reading failed.')
    }
    totalFileReader.onerror = () => {
      this.onDelete()
    }
    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))
    }
    // loadNext()
    return false
  }
  /**
@@ -164,7 +251,7 @@
      fileList: value,
      action: baseUrl,
      method: 'post',
      multiple: true,
      multiple: false,
      onChange: this.onChange,
      onRemove: this.onRemove,
      data: this.getExtraData,