SOURCE

console 命令行工具 X clear

                    
>
console
// 分割文件
function splitBlob(blob, chunkSize) {
  if (!chunkSize|| blob.size <= chunkSize) return [blob]
  const chunkList = []
  const filesize = blob.size
  let start = 0
  let end = 0
  while (start < filesize) {
    end = start + chunkSize
    if (end > filesize) end = filesize
    const chunk = blob.slice(start, end)
    chunkList.push(chunk)
    start = end
  }
  return chunkList
}

// 文件分割处理
async function blobSplitHandle ({ blob, chunkSize, chunkHandle, onProgress }) {

  // 任务列表
  const taskList = splitBlob(blob, chunkSize).map((chunk, index) => {
    return {
      index,
      chunk,
      chunkRate: chunk.size / blob.size,
      loaded: 0,
      total: 0,
      scheduleRate: 0
    }
  })

  // 更新进度
  function updateProgress () {
    const scheduleRate = taskList.reduce((value, task) => {
      if (task.scheduleRate) return (value + (task.chunkRate * task.scheduleRate))
      return value
    }, 0)

    onProgress && onProgress({
      loaded: parseInt(blob.size * scheduleRate),
      total: blob.size
    })
  }


  // 监听进度
  function handleUploadProgress (task, event) {
    const { loaded, total } = event

    task.loaded = loaded
    task.total = total
    task.scheduleRate = loaded / total

    updateProgress()
  }

  // 遍历上传
  let result = undefined
  for (const task of taskList) {
    result = await Promise.resolve(chunkHandle(task.chunk, task.index, handleUploadProgress.bind(task, task)), result)
    handleUploadProgress(task, task)
  }

  // 对其进度
  onProgress && onProgress({
    loaded: blob.size,
    total: blob.size
  })

}
<form>
	<div class="form-group">
		<label for="exampleFormControlFile1">选择文件</label>
        <input type="file" class="form-control-file" id="file" onChange="upload()">
        <div class="progress">
            <div class="progress-bar progress-bar-striped" style="width: 0%"></div>
        </div>
    </div>
</form>

<script type="text/javascript">
    
    function upload() {

        // 文件
        const blob = document.getElementById('file').files[0]
        
        // 每个块上传
        function chunkHandle (chunk, index, handleProgress) {
            const formData = new FormData()
            formData.append('file', chunk, `${blob.name}_chunk${index}`)
            return axios.post('https://jsonplaceholder.typicode.com/posts/', formData, {
                onUploadProgress: handleProgress
            })
        }

        // 进度条事件
        function onProgress (event) {
            const { loaded, total } = event

            const schedule = Number(loaded / total  * 100).toFixed(2)
            document.querySelector('.progress-bar').style.width = `${schedule}%`
            console.log(loaded, total, schedule)

        }

        // 请求
        blobSplitHandle({
            blob: blob,
            chunkSize: 5 * 1024 * 1024,
            chunkHandle: chunkHandle,
            onProgress: onProgress
        }).then(() => {
            console.log('上传完成')
        }, (error) => {
            console.error(error)
            console.log('上传失败')
        })

    }

</script>

本项目引用的自定义外部资源