小工具知识网

当前位置: 首页 > 行业知识 > 前端大文件分片上传 进度条展示 上传暂停、开始、取消

行业知识

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

2026-11-16 02:20:14 来源:互联网转载

实现的效果:

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

2、进度条展示进度

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

实现关键点:

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

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);      });}

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

                    {{ 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);    }

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

上一篇:代理服务器在哪里买?

下一篇:【IC设计】Scala、Chisel、Chiseltest版本兼容信息