XHR 文件上传进度条原理解析

5,963 阅读2分钟

前言

前几天再写自己的一个后台模板。有个功能是实现上传进度条。

那么ojk了,上网上找下上传进度条的实现。

(这个截图是我已经写的好的)

此刻我突然想到了为啥我不看看ng-zorro 得代码怎么写的,他肯定写的有上传进度条得功能……

github.com/NG-ZORRO/ng… 第248行处发现了这个……

    return this.http.request(req).subscribe((event: HttpEvent<{}>) => {
      if (event.type === HttpEventType.UploadProgress) {
        if (event.total > 0) {
          // tslint:disable-next-line:no-any
          (event as any).percent = event.loaded / event.total * 100;
        }
        args.onProgress(event, args.file);
      } else if (event instanceof HttpResponse) {
        args.onSuccess(event.body, args.file, event);
      }
    }, (err) => {
      this.abort(args.file);
      args.onError(err, args.file);
    });

HttpEventType 是不同种类的 HttpEvent 的枚举类型(官方解释)

好吧,angular已经完成了一大部分得东西。

问题来了

angular得已经帮我们实现了,那么jQuery得网上也能找到,那么原生的js上传进度条又该怎么实现?

在社区找到一份代码。 segmentfault.com/a/119000001…

    var xhr = new XMLHttpRequest();  // 先new 一个XMLHttpRequest。
    xhr.open('POST', 'url');   // 设置xhr得请求方式和url。
   
    xhr.onreadystatechange = function() {   // 等待ajax请求完成。
        if (xhr.status === 200) {&emsp;&emsp;
            console.log(xhr.responseText);
        } else {
            console.log('上传出错');
        }
    };
    // 获取上传进度
    xhr.upload.onprogress = function(event) { 
        console.log(event.loaded)
        console.log(event.total)
        if (event.lengthComputable) {
            var percent = Math.floor(event.loaded / event.total * 100);
            document.querySelector("#progress .progress-item").style.width = percent + "%";
            // 设置进度显示
            console.log(percent)
        }
    };
    xhr.send(fd);

XHR 接口规范: xhr.spec.whatwg.org/

重要的东西来了。就是 upload.onprogress 点上去会发现

好了你就是我们大Boss了,可以看到这里有辣么多方法……我们只需要用 onprogress。

onprogress 是ProgressEvent类型.

ProgressEvent 有三个对象

  • lengthComputable 只读属性是一个布尔Boolean 标志,表示ProgressEvent 所关联的资源是否具有可以计算的长度 (MDN)

  • loaded表示已经接收的字节数

  • total 表示文件的字节

所以

文件上传的进度: onprogress监听到 ProgressEvent的到已经上传完得字节 / 上传文件得字节 * 100

vue 怎么办呢?

jQuery的话百度一搜一大把,

走原生:

element 上传走的就是原生的js

github.com/ElemeFE/ele… (第39开始)

  if (xhr.upload) {
    xhr.upload.onprogress = function progress(e) {
      if (e.total > 0) {
        e.percent = e.loaded / e.total * 100;
      }
      option.onProgress(e);
    };
  }

走axios:

axios也是已经实现了。

github.com/axios/axios…

    if (typeof config.onUploadProgress === 'function' && request.upload) {
      request.upload.addEventListener('progress', config.onUploadProgress);
    }

end

提前给大家拜个年:新年快乐……