JS 大文件分片上传断点续传类实现

本文介绍了一个使用JavaScript实现的大文件分片上传类,支持断点续传功能。类初始化时接收文件对象,通过计算文件MD5和获取服务器信息来确定上传分片。整体流程包括计算MD5、文件信息确认、分片上传、进度计算和上传控制。文章提供了完整的代码示例,并指出文件上传的成功依赖于前后端的协同工作。
摘要由CSDN通过智能技术生成


场景及概述

前端web应用上传大文件,经常遇到文件上传途中用户不小心关闭了页面、网络中断等情况,文件分片上传➕断点续传能够将大文件分片发送多个分片上传请求,在遇到上传中断等情况时,可以根据服务器返回的已有分片筛选未上传的分片进行上传,减少服务器的存储压力,本文将实现一个具备以上功能的文件上传类

功能及整体流程设计

该类具备基本文件上传功能,此外能够对文件分片、在上传前将文件信息发送给服务器确定文件在服务器的信息后确定上传分片序号进行上传、中断上传。这里使用md5进行文件摘要,整体流程设计如下
文件分片上传流程图

关键步骤解析

1.类初始化

使用外部传入的参数初始化类,option中含有待上传的文件对象,并初始化所有变量,waitUploadChunks是根据allChunks和uploadedChunks计算出来的上传分片,fileMd5用于发送给后端确认该文件是否已经完整上传到服务器

constructor(options) {
   
    // 初始化配置
    this.options = options
    // 默认的单个分片大小
    this.defaultChunkSize = 1024 * 1024 * 10
    // 默认的上传地址
    this.defaultApi = '/api/file-cloud-web-server/sharding-file/upload'
    // 文件所有分片序列
    this.allChunks = []
    // 已上传成功的分片序列
    this.uploadedChunks = []
    // 等待上传的分片序列
    this.waitUploadChunks = []
    // 文件MD5
    this.fileMD5 = ''
    // 最大上传进程数 默认同时上传5个
    this.maxThreads = 5
    this.uploadStatus = {
   
      preparing: 'preparing',
      uploading: 'uploading',
      success: 'success',
      failed: 'failed',
    }
    // 上传分片集合
    this.uploadPieces = []
    // 上传进度
    this.uploadProgress = 0
  }

2.整体流程控制

set_start方法确定整个上传的整体流程,计算文件md5-获取文件在服务器的位置信息-修改文件上传状态-加载文件分片上传

set_start() {
   
    this.getFileMD5(() => {
   
      this.getFileInfo(() => {
   
        this.completed(this.uploadStatus.uploading)
        this.loadNextChunk()
      })
    })
  }

3. 计算文件md5并获取文件在服务器的信息

readNext方法中对文件进行分片,同时使用fileReader 和 sparkMd5对文件计算md5,后续通过请求后端接口,将需要上传的分片序号放在waitUploadChunks 中

getFileMD5(callback) {
   
    let chunkNumber = 0
    const spark = new SparkMD5.ArrayBuffer()
    const reader = new FileReader()
    // 使用reader将文件分片并读入
    // onload 为reader读取完分片后的操作
    reader.onload = (e) => {
   
      spark.append(e.target.result)
      chunkNumber++
      if (chunkNumber < this.totalChunks) {
   
        this.readNext(chunkNumber, reader)
      } else {
   
        // 已经将所有分片读取完成
        this.fileMD5 = spark.end()
        console.log(`文件MD5:${
     this.fileMD5}`)
        // 下一步:获取文件在服务器的位置
        callback()
      }
    }
    this.readNext(chunkNumber, reader)
  }

4. 上传分片

使用formData上传分片,用axios的CancelToken 获取中断该分片上传的方法;此处需要注意的是文件上传进度的计算,由于文件被分成了多个分片上传,请求的字节流包括的多个上传请求的请求头,因此每个请求的字节流之和会大于原文件的实际大小,在这里我使用的单个分片的上传进度累加获得整个文件的上传进度

uploadFileBinary(chunkNumber, filePath) {
   
    const url = this.options.url || this.defaultApi
    //声明一个formdata对象,用于存储file文件以及其他需要传递给服务器的参数
    const formData = new FormData()
    formData.append('chunkNumber', chunkNumber)
    formData.append('totalChunks', this.totalChunks)
    formData.append('identifier', this.fileMD5)
    formData.append('totalSize', this.options.file.fileObj.size)
    formData.append('filename', this.options.file.fileObj.name || '')
    formData.append('file', this.allChunks[chunkNumber])

    // 中断请求准备
    const CancelToken = axios.CancelToken //获得Cancel对象
    const that = this
    axios({
   
      url,
      method: 'post',
      headers: {
   
        'Content-Type': 'multipart/form-data',
      },
      timeout: 18000000,
      data: formData,
      onUploadProgress: (res) => {
   
        // 计算每个分片的占比
        const rate = 100 / this.total
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值