bigfile-upload icon indicating copy to clipboard operation
bigfile-upload copied to clipboard

前端 - 大文件上传的解决方案

【前端】大文件上传的解决方案

本项目包含前端和后端(后端是nodejs写的),完美展示了大文件上传在实际项目中的使用方法。

文章最后包含本项目中使用到的一些技术点、以及相关技术点解读。

运行项目

# 克隆项目
git clone https://github.com/Neveryu/bigfile-upload.git

# 进入项目
cd bigfile-upload

# 安装依赖
npm i

# 运行
npm start

浏览器访问:http://localhost:3000/

说明

思路说明

1、暂时设置一个切片大小为200kb。(具体数值可自己设定,或者动态计算一个切片应该多大合适)

2、前端将文件分割为一个个的小文件(切片)。

  • 如果以文件名后面加-${index}来标示每一个切片名的话,那么如果这个文件改名了,那么每个文件切片的命名也会发生改变。所以要生成文件的hash,一个文件不管怎么改名,文件的hash不会改变,所以用文件hash来作为唯一标识,解决文件名不确定性的问题。

3、切片上传

  • 上传之前先向后端发送一个请求,把文件hash传过去,进行一个校验;验证文件是否已上传,如已上传,则不用上传,相当于秒传成功;如果文件不在服务器中,则返回已经上传在服务器中的切片数组,来判断文件是否已经上传了一部分,那么就是断点续传;如果后端返回的数组是空,则表明这个文件从来没有被上传过。

4、全部上传完成后,向后端发送一个请求,请求将所有的切片合并为一个完整的文件。

5、【补充功能】显示上传进度条。

  • 上传进度包含两个:一个是每个切片的上传进度,另一个是整个文件的上传进度。而整个文件的上传进度是基于每个切片上传进度计算而来,所以我们先实现切片的上传进度。

  • 为了能看到每个切片的上传的进度,所以把每个切片的大小设置大一点,10kb太小了,一下就上传完了,看不到进度。我们可以把每个切片的大小设置为2M,同时,选一个大点的文件来试试。

相关知识点以及解读说明

1、如何计算hash、如何切片

  • 计算文件 hash 使用的是 spark-md5,详情可以查看 public/hash.js 文件。
  • 对文件进行 file.slice(cur, cur + size) 的操作即可将文件分割为多个小的文件片段。

2、上传文件切片、计算上传进度

  • 分片后的小文件数组,循环操作,分别直接上传,在原生的 xhr 中有一个 upload.onProgress 属性可以监听到上传的进度;并进行计算。

3、暂停、恢复

  • 暂停时,对当前所有的 xhr 进行 abort()
  • 恢复时,重新进行校验,然后上传剩余没有上传的部分。

3、如何合并文件

  • 使用 nodejs 的读写流(readStream/writeStream),将所有切片的流传输到最终文件的流里。

最后

项目代码有完善的注释和说明,更详细的理解请查阅代码和运行示例。