sakila1012 / blog

记录自己学习工作中的心得
10 stars 3 forks source link

上传整理 #65

Open sakila1012 opened 4 years ago

sakila1012 commented 4 years ago

上传整理

写在前面

对比了百度企业盘,天翼企业盘是如何实现文件并发上传的

整理上传得过程

并发上传要考虑很多内容

MD5计算,队列,数据结构,大文件分片,错误处理,暂停,移除,错误重传等。 发布订阅模式

移除文件:分为正在上传,正在计算MD5值,待上传。 暂停文件:只能指正在上传的文件,中断上传的请求,同时将文件的状态设置为暂停状态。

错误重传是指上传文件出错,分为手动点击重传,以及自动设置分块上传错误重传。

对上传列表的文件进行暂停,暂停后还可以点击继续上传。

设置重传,是指由于网络原因导致的上传失败,然后再重新进行上传,同时也要设置重传的次数,一般为3次。

上传过程

上传分为普通上传和分块上传 普通上传:预上传,上传 分块上传:预上传,上传,合并上传

实现方案

1、百度webuploader插件的例子

2、使用 web worker 来创建多个线程,在每个线程中处理上传,在每个simple-uploader.js 进行分块上传处理

提供以下功能:

文件拆分成指定大小的块

分块多线程发起上传请求

提供暂停功能

分块上传失败后重试

文件并发

秒传

断点续传

在上传的过程中,需要处理文件的MD5值计算,文件的分块,文件暂停,续传,移除,重传,需要对这些设计数据结构来进行存储。 对于单次选择多个文件上传和单次选择一个文件的处理方式,会有所不同,是在上传文件的分块数,如果一次选择多个文件,在web worker中处理分块并发设置为3,如果只是一个文件上传,在 web worker 设置的分块并发是3。

设置文件的的并发,可以跟电脑的核心(navigator.hardwareConcurrency)来进行配置,但一般文件的并发不要设置的太高,不要超过6。

设置一个初始值 initValue 为6 如果是首次开始上传,则需要处理

设置上传需处理的数组 workerFileUploading: 正在上传的文件, workerFilePause:被暂停的文件, workerFileWaiting:等待上传的文件, fileList: 存储所有的文件

在某文件上传成功,暂停,上传失败,移除正在上传的文件,同时要有一个函数实现继续下一个文件上传 nextFile(),

在触发选择的按钮,获取选择的文件,对这些文件进行下面的操作: 对于每个文件要独立生成一个唯一的id,通过这个id来查找要操作的文件。

然后将这些文件加入到fileList数组中,如果选择的文件数量大于6,在这个数组中剪取前6,将这些文件放到 workerFileUploading中,并将这些文件的信息通过worker postMessage 传递给worker子线程中,在子线程中进行文件的MD5计算,文件的预上传,分块上传,如果文件的大小大于分块的大小,还要有文件的合并上传,以及文件各种过程的状态传递给上传列表。在主线程中,对收到的数据信息进行状态的更新,并将状态信息更改至上传列表。

如果在上传过程中,出现异常: 某个块上传失败,会进行重传,一般设置为3次,若重传仍失败,将该块放入到workerFilePasue中,进入下一个文件上传 若整个文件上传失败,则将整个文件放入到workerFilePasue数组中,上传过程,如果文件被暂停,则通过worker主线程将消息传至子线程中,在子线程中中断上传的文件,同时,在主线程中,将暂停的文件放入到workerFilePause,该文件也要从正在上传的workerFileUploading中移除。

移除正在上传的文件: 主线程将该文件从workerFileUploading中移除,从上传列表中移除,主线程中发消息至子线程中,取消文件上传

移除等待上传的文件: 直接将该文件从fileList中移除,同时也要从workerFileWaiting中移除,上传列表移除该文件。

移除正在计算MD5值的文件: 主线程将该文件从workerFileUploading中移除,从上传列表中移除,主线程中发消息至子线程中,取消文件上传

暂停是指正在上传的文件,正在计算MD5值的文件和等待中的文件是不能进行暂停的,但这些文件是可以移除的

暂停了某个文件,移除了某个正在上传的文件,移除某个正在计算MD5值的文件,以及某个文件上传失败,某个文件上传成功,都是要触发待上传队列中的文件。

如果上传列表中某个文件上传成功,该文件也要从workerFileUploading中移除,更新该文件在上传列表中的状态。

暂停的文件续传: 续传有两种情况,一种是没有可并发上传的线程了,这个时候,将该文件放到workerFilePause的头部,第二种是直接进行上传, 将暂停的worker从workerFilePause移出,放入至workerFileUploading,同时,主线程往子线程中发消息开始文件续传。

上传失败的文件重传: 会进行文件重新上传,也即,将该文件从workerFilePause中移出,放入到workerFileUploading中,主线程通知子线程开始文件的续传。

关闭整个模态框: 主线程中发消息至子线程中,在子线程中取消所有正在上传的文件,主线程清空上传列表,workerFileUploading,workerFilePause,workerFileWaiting均置空,模态框关闭。

对于IE浏览器中的性能问题,主要是垃圾回收问题,如果不进行垃圾回收的话,内存会一直累积,超过一定的内存的话,就会出现 image 需要对IE浏览器进行垃圾回收优化,避免出现内存累积上升。需要对分块上传过程,一旦某个分块上传成功后,则需要对该分块进行清除引用。

我突然发现了一个问题,一次性选择300个文件,而且这300个文件还是非常大的情况, 我一直暂停文件,岂不是要有300个worker,这种情况下,会不会有问题呢?需要进一步测试。 worker数量多的情况下,也是很耗内存的,对于IE浏览器会不会也是个问题。

在IE 11浏览器中,频繁点击暂停正在上传的文件,也会出现IE内存累积上升,直接浏览器内存泄漏,刷新整个页面,上传失败。 在每次暂停文件上传时,都要对引用的数据进行垃圾回收。垃圾回收还有问题,还需进一步优化和完善? 有没有可能是IE浏览器限制worker的使用量。 暂停24个文件后,就不可以继续操作了,没有继续上传待上传的文件,此时点击续传也是没有效果的。 关键是IE 没有加载资源失败有任何的提示