9

在本周,潘老师要求对文件上传功能进行一下修改,要求弹出一个弹窗并显示上传进度,开始的时候想着还觉得这是个挺高级的功能,现在才发现前人又一次帮我们铺好了路。

通用实现

标题是angular,但先介绍的方法却和angular无关,而是一个在js中都可以通用的方法——XMLHttpRequest

XMLHttpRequest

XMLHttpRequest 对象用于在后台与服务器交换数据。

XMLHttpRequest 对象是_开发者的梦想_,因为您能够:

  • 在不重新加载页面的情况下更新网页
  • 在页面已加载后从服务器请求数据
  • 在页面已加载后从服务器接收数据
  • 在后台向服务器发送数据

所有现代的浏览器都支持 XMLHttpRequest 对象。

关于它的详细内容可以查看这篇文档,这里就不在细说了。

XMLHttpREquest.upload.onprogress

回到正题,要实现文件上传进度很简单,upload.onprogress事件回调方法可用于跟踪资源上传的进度,它的event参数对象包含两个重要的属性loaded和total。分别代表当前已上传的字节数(number of bytes)和文件的总字节数。既然知道了这两个属性,上传进度,上传速度等等不就都可以算出来了:

      // 增加上传过程事件
      xhr.upload.addEventListener('progress', (e: ProgressEvent) => {
      // lengthComputable属性代表文件总大小是否可知。如果 lengthComputable 属性的值是 false,那么意味着总字节数是未知并且 total 的值为零。
        if (e.lengthComputable) {
        // 上传的百分比
          const percentage = Math.round((e.loaded * 100) / e.total);
          // 耗费的时间 , time 是开始的时间
          const diff = new Date().getTime() - time;
          // 上传的速度
          speed = Math.round(e.loaded / diff * 1000);
          // 剩余时间
          eta = Math.ceil((e.total - e.loaded) / speed);
        }
      }, false);

注意事项

1.若是再浏览器的控制台中 new 一个XHR对象,并使用点运算符,可以发现有一个onprogress事件监听器
image.png
虽然,这看着和我们用到的差不多,但这可不是我们需要的,

后者是用于加载资源时,而前者用于资源上传时

2.测试的时候最好网速慢一点,或者文件大一些,否着可能会出现看不出效果,一来就是百分百,因为xhr.upload.onprogress在上传阶段(即xhr.send()之后,xhr.readystate=2之前)触发,每50ms触发一次。

ps: 网速可以通过控制台设置
image.png

angular实现

后来才发现angular已经给我们封装,整体上都是差不多的

upload(file: File) {  
  if (!file) {  
  return;  
 }  
 
  // 创造请求对象  
  // reportProgress 告诉 HttpClient 监听并返回XHR progress events事件. 
  const req = new HttpRequest('POST', '/upload/file', file, {  
  reportProgress: true  
  });  
  
  // 产生一个 event 流  
  return this.http.request(req).subscribe((event: HttpEvent<{}>) => {  
  if (event.type === HttpEventType.UploadProgress) {  
   if (event.total > 0) {  
  // 计算上传的百分比  
  const percent = event.loaded / event.total * 100;  
 } }  });

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

这是anular的官方demo可以参考。


笙歌会停
1k 声望45 粉丝

代码成就万世基积沙镇海 梦想永在凌云意意气风发