前端大文件分片上传 进度条展示 上传暂停、开始、取消

03-27 1729阅读 0评论

前端大文件分片上传 进度条展示 上传暂停、开始、取消

前端大文件分片上传 进度条展示 上传暂停、开始、取消,前端大文件分片上传 进度条展示 上传暂停、开始、取消,词库加载错误:未能找到文件“C:\Users\Administrator\Desktop\火车头9.8破解版\Configuration\Dict_Stopwords.txt”。,使用,前端,流程,第2张
(图片来源网络,侵删)

实现的效果:

1、多个大文件(支持10个G以上)分片上传

2、进度条展示进度

3、控制文件上传暂停和取消

实现关键点:

1、文件预处理(md5计算、请求和进度处理等)

前端大文件分片上传 进度条展示 上传暂停、开始、取消,前端大文件分片上传 进度条展示 上传暂停、开始、取消,词库加载错误:未能找到文件“C:\Users\Administrator\Desktop\火车头9.8破解版\Configuration\Dict_Stopwords.txt”。,使用,前端,流程,第3张
(图片来源网络,侵删)

2、分片上传的流程(查询已上传分片、文件合并等)

3、文件的暂停、开始、取消

文件预处理

首先使用file类型的input框获取文件,对文件进行深拷贝,再清空input的value值(防止input的change事件不被触发)。

let files = e.target.files;
 let copiedFiles = []
 for(let i = 0; i  

对文件进行处理,核心思想是为每个文件构造一个对象,封装该文件的md5信息(用于标识该文件)和进度、请求、取消标识(用于文件的暂停)等信息。

async bigFileChange(files) {
      // 新增的文件
      let newFiles = [];
      // 筛选出检验合格的文件
      let okFileIndexs = this.checkRules(files);
      for (let i = 0; i  

计算md5值采用的是SparkMD5,为了减少计算量,采用文件的第一块的md5作为整个文件的md5。

firstChunkMd5(file, chunkSize) {
      return new Promise((resolve, reject) => {
        const fileReader = new FileReader();
        const spark = new SparkMD5.ArrayBuffer();
        const chunk = file.slice(0, chunkSize);
        fileReader.onload = function (event) {
          spark.append(event.target.result);
          const md5 = spark.end();
          resolve(md5);
        };
        fileReader.onerror = function () {
          reject(new Error("File read error."));
        };
        fileReader.readAsArrayBuffer(chunk);
      });
}

在界面上为每个文件创建进度条。

前端大文件分片上传 进度条展示 上传暂停、开始、取消,前端大文件分片上传 进度条展示 上传暂停、开始、取消,词库加载错误:未能找到文件“C:\Users\Administrator\Desktop\火车头9.8破解版\Configuration\Dict_Stopwords.txt”。,使用,前端,流程,第4张
(图片来源网络,侵删)
  
    
      
        {{ f.file.name }}
      
    
    
      {{ f.newSize }}
    
    { f.progress }}%
     -->
    
      {{ f.status }}
    
    
      
        暂停
      
      
        开始
      
      
        取消
      
    
  
  
    
  

分片上传

首先查询文件已经上传的分片数,如果全部上传了,进度立即更新为100%(秒传),如果没完全上传,则上传未上传的分片并实时更新进度,各分片上传完毕后请求合并,采用轮询检测合并进度。

this.checkFile(fileObj, chunks)
          .then(async (res) => {
            console.log(res);
            if (res.data.data.completed) {
              // 如果当前文件已经上传成功 则无需继续上传
              fileObj.progress = 100;
              fileObj.status = "上传成功";
              // 为成功上传的附件添加id
              if (res.data.data.attachmentId) {
                fileObj.attachmentId = res.data.data.attachmentId;
              }
              this.$forceUpdate(); // 强制重新渲染组件
              this.$emit("fileUpdate");
            } else {
              // 当前文件没有上传成功
              // 获取已经上传的分片数组
              let uploadedChunks = res.data.data.uploadChunks;
              // 获取当前的进度
              let newProgress = parseInt(
                (uploadedChunks.length / chunks) * 100
              );
              fileObj.progress = newProgress;
              this.$forceUpdate(); // 强制重新渲染组件
              // 文件均已上传完 但还未合并
              if (res.data.data.canMerge || uploadedChunks.length == chunks) {
                this.mergeBigFile(fileObj)
                  .then((res) => {
                    fileObj.status = "合并中";
                    this.$forceUpdate(); // 强制重新渲染组件
                    // 先清除该文件上次的合并计时器
                    if (fileObj.mergeTimer) {
                      clearInterval(fileObj.mergeTimer);
                    }
                    fileObj.mergeTimer = setInterval(() => {
                      this.getMergeProcess(fileObj).then((res) => {
                        if (res.data.data.completed) {
                          fileObj.status = "上传成功";
                          // 为成功上传的附件添加id
                          if (res.data.data.attachmentId) {
                            fileObj.attachmentId = res.data.data.attachmentId;
                          }
                          this.$forceUpdate(); // 强制重新渲染组件
                          // 合并完成
                          fileObj.requests = [];
                          fileObj.cancelTokens = [];
                          clearInterval(fileObj.mergeTimer);
                          this.$emit("fileUpdate");
                        }
                      });
                    }, 2000);
                  })
                  .catch((error) => {
                    console.error("上传失败:", error);
                    fileObj.status = "上传失败";
                    if (fileObj.mergeTimer) {
                      clearInterval(fileObj.mergeTimer);
                    }
                    this.$forceUpdate();
                  });
              } else {
                // 文件还没上传完
                let currentChunk = 0;
                // 上传没有上传的部分
                while (currentChunk  {
                      console.log(res);
                      // 进行进度控制
                      let progress = parseInt(
                        (res.data.data.uploadChunks.length / chunks) * 100
                      );
                      if (progress > fileObj.progress) {
                        fileObj.progress = progress;
                        this.$forceUpdate(); // 强制重新渲染组件
                      }
                      // 进行文件的合并控制
                      if (res.data.data.canMerge) {
                        // 文件可以合并了
                        this.mergeBigFile(fileObj)
                          .then((res) => {
                            fileObj.status = "合并中";
                            this.$forceUpdate(); // 强制重新渲染组件
                            // 先清除该文件上次的合并计时器
                            if (fileObj.mergeTimer) {
                              clearInterval(fileObj.mergeTimer);
                            }
                            fileObj.mergeTimer = setInterval(() => {
                              this.getMergeProcess(fileObj).then((res) => {
                                if (res.data.data.completed) {
                                  fileObj.status = "上传成功";
                                  // 为成功上传的附件添加id
                                  if (res.data.data.attachmentId) {
                                    fileObj.attachmentId =
                                      res.data.data.attachmentId;
                                  }
                                  this.$forceUpdate(); // 强制重新渲染组件
                                  // 合并完成
                                  fileObj.requests = [];
                                  fileObj.cancelTokens = [];
                                  clearInterval(fileObj.mergeTimer);
                                  this.$emit("fileUpdate");
                                }
                              });
                            }, 2000);
                          })
                          .catch((error) => {
                            console.error("上传失败:", error);
                            fileObj.status = "上传失败";
                            if (fileObj.mergeTimer) {
                              clearInterval(fileObj.mergeTimer);
                            }
                            this.$forceUpdate();
                          });
                      }
                    })
                    .catch((error) => {
                      if (axios.isCancel(error)) {
                        console.log("上传已暂停或取消");
                      } else {
                        console.error("上传失败:", error);
                        fileObj.status = "上传失败";
                        this.$forceUpdate();
                      }
                      fileObj.requests = [];
                      fileObj.cancelTokens = [];
                    });
                }
              }
            }
          })
          .catch((error) => {
            console.error("Error:", error);
            fileObj.status = "上传失败";
            this.$forceUpdate();
});

上传暂停、开始、取消

暂停上传即根据取消标识将当前文件的所有请求进行取消。

pauseBigFile(fileObj) {
      fileObj.cancelTokens.forEach((item) => {
        item.cancel("上传暂停");
      });
      fileObj.isPaused = true;
      fileObj.status = "已暂停";
      this.$forceUpdate(); // 强制重新渲染组件
    }

开始上传即对文件重新进行上传处理。

restartBigFile(fileObj) {
      fileObj.isPaused = false;
      fileObj.status = "上传中";
      this.$forceUpdate(); // 强制重新渲染组件
      fileObj.requests = [];
      fileObj.cancelTokens = [];
      this.uploadBigAttachment(fileObj);
    }

取消上传是将文件所有请求取消并发送请求删除文件,这里不加赘述。


免责声明
本网站所收集的部分公开资料来源于AI生成和互联网,转载的目的在于传递更多信息及用于网络分享,并不代表本站赞同其观点和对其真实性负责,也不构成任何其他建议。
文章版权声明:除非注明,否则均为主机测评原创文章,转载或复制请以超链接形式并注明出处。

发表评论

快捷回复: 表情:
评论列表 (暂无评论,1729人围观)

还没有评论,来说两句吧...

目录[+]