一、准备文件上传的条件:
1、安装nodejs环境
2、安装vue环境
3、验证环境是否安装成功
二、实现上传步骤
1、前端部分使用 vue-cli 脚手架,搭建一个 demo 版本,能够实现简单交互:
2、安装 axios 实现与后端交互:
3、后端使用 node-koa 框架:
4、前端实现上传请求:
5、node 接收文件接口:
以上全部过程就实现了一个简单的文件上传功能。
这种实现方式上传功能对于小文件来说没什么问题,但当需求中碰到大文件的时候,能解决上传中遇到的各种问题,比如网速不好时、上传速度慢、断网情况、暂停上传、重复上传等问题。想要解决以上问题则需要优化前面的逻辑。
1、分片逻辑如下:
- 由于前端已有 Blob Api 能操作文件二进制,因此最核心逻辑就是前端运用 Blob Api 对大文件进行文件分片切割,将一个大文件切成一个个小文件,然后将这些分片文件一个个上传。
- 现在的 http 请求基本是 1.1 版本,浏览器能够同时进行多个请求,这将用到一个叫 js 异步并发控制的处理逻辑。
- 当前端将所有分片上传完成之后,前端再通知后端进行分片合并成文件。
2、在进行文件分片处理之前,先介绍下 js 异步并发控制:
js 异步并发控制的逻辑是:运用 Promise 功能,定义一个数组 fetchArr,每执行一个异步处理往 fetchArr 添加一个异步任务,当异步操作完成之后,则将当前异步任务从 fetchArr 删除,则当异步 fetchArr 数量没有达到最大数的时候,就一直往 fetchArr 添加,如果达到最大数量的时候,运用 Promise.race Api,每完成一个异步任务就再添加一个,当所有最后一个异步任务放进了 fetchArr 的时候,则执行 Promise.all,等全部完成之后则执行回调函数。
上面这逻辑刚好适合大文件分片上传场景,将所有分片上传完成之后,执行回调请求后端合并分片。
前端改造:
1、定义一些全局参数:
2、文件分割方法:
以上方式的处理逻辑:定义一个切片缓存数组,当文件进行分片之后,将缓存所有的分片信息、根据最大分片大小计算分片数量、计算整个文件的 hash (spark-md5) 值,这将意味着,只要文件内容不变,这 hash 值也将不变,这涉及到后面的秒传功能、然后进行文件分片。
3、改造上传方法:
注意:以上代码中设置当文件大小大于分片大小的5倍进行分片上传。
4、定义分片上传请求(sendRequest)和合并请求(chunkMerge):
5、分片请求将结合上面提到的 JS 异步并发控制:
6、切片上传请求:
7、切片合并请求:
前端处理文件分片逻辑代码已完成
后端处理
后端部分就只新增两个接口:分片上传请求和分片合并请求:
1、分片上传请求:
2、分片合并请求:
切片上传成功与文件合并截图:
1、前端暂停,续传功能:
2、js 新增主动暂停和续传方法,比较简单,这里没有做停止正在执行的请求:
前端大文件的分片上传就差不多了。还可以优化的一点,在进行文件 hash 求值的时候,大文件的 hash 计算会比较慢,这里可以加上 html5 的新特性,用 Web Worker 新开一个线程进行 hash 计算。
GitHub:https://github.com/554246839/file-upload