文件上传进度管控

136 阅读2分钟

开启掘金成长之旅!这是我参与「掘金日新计划 · 2 月更文挑战」的第 19 天,点击查看活动详情

上传图片进度管控

首先图片上传进度在没有开始上传的时候进度一定是%0,然后使用fromdata上传文件。axios封装了一个方法,onUploadProgress,文件上传过程中会触发多次。每次会返回一个图片传输的进度和文件的总大小,简单的数学公式,使用当前传送完毕的数据(loaded)除以文件总大小,就得到了文件的已经传出的百分比了,然后乘以100,就是该文件上传的进度了

  let formData = new FormData()
    formData.append('file', file)
    formData.append('filename', file.name)
      const res = await uploadSingle(formData, {
        onUploadProgress(e) {
          const { loaded, total } = e
          const v = (loaded / total).toFixed(2) * 100 + '%'
        },
      })

多个文件上传进度管控

多个文件上传的进度管控和单个文件上传进度管控原理相同,只不过是写了一个循环,让每个图片都上传一下,这个案例是使用react搞的,所以会有个设置状态的方法,这些细节可以忽略

 const tasklist = fileList.map(({ file, name, key },index) => {
      let formData = new FormData()
      formData.append('file', index==2?"file":file)
      formData.append('filename', name)
      return uploadSingle(formData, {
        onUploadProgress(e) {
          const { loaded, total } = e
          const p = (loaded / total).toFixed(2) * 100 + '%'
          setFileProgress(p, key)
        },
      })
        .then((res) => {
          if (!(res.code === 0)) {
            throw new Error()
          }
          setFileProgress('100%', key)
          return res
        })
        .catch(() => {
          setFileProgress('0%', key)
          return false
        })
    })
    const res = await Promise.all(tasklist)
    if (res.every((item) => item)) {
      message.success('上传成功')
    } else {
      message.error('上传失败')
    }

接口是这样的

export const uploadSingle = (fm, config={}) => {
  return uploadHttp.post('/upload_single', fm, config)
}

事出有因

用户反馈:图片上传过程中,如果网络比较慢,会发现上传图片后没有一点反应,体验性很差,图片回显也比较慢

解决思路:通过XMLHttpRequest的progress来实现监听图片上传的进度,实时显示百分比,后台保存图片成功后再将图片转为Base64编码的字符串在前端显示出来,这样可以很大程度提高用户体验

需要达到的效果:

1、用户可以看到图片上传进度条百分比

2、提升图片回显速度(将图片转为Base64编码的字符串在前端显示)

axios 是对如下原生js封装

    var xhr = new XMLHttpRequest();
    //上传中设置上传的百分比
    xhr.upload.addEventListener("progress", function(evt){
        if (evt.lengthComputable) {
            var percentComplete = Math.round(evt.loaded * 100 / evt.total);
            if (percentComplete == 100){
                setTimeout(function () {
                    document.getElementById("showProgress").innerHTML = "已上传"+percentComplete+"%";
                },1500)
            }else{
                document.getElementById("showProgress").innerHTML = "已上传"+percentComplete+"%";
            }
        }else {
            document.getElementById("showProgress").innerHTML = "无法计算";
        }
    }, false);
    //请求完成后执行的操作
    xhr.addEventListener("load", function(evt){
        var message = evt.target.responseText,
                obj = eval("("+message+")");
        $("#uploadImage").attr("src",obj);
        document.getElementById("showProgress").style.display="none";
         alert("上传成功!");
 
    }, false);