vue分片上传大文件

一、npm 安装 md5

npm i spark-md5 --save



import SparkMD5 from "spark-md5";
/**
 * 获取文件MD5
 * @param file
 * @returns {Promise}
 */
export function getFileMd5(file, chunkCount, chunkSize) {
  return new Promise((resolve, reject) => {
    let blobSlice = File.prototype.slice || File.prototype.mozSlice || File.prototype.webkitSlice;
    let chunks = chunkCount;
    let currentChunk = 0;
    let spark = new SparkMD5.ArrayBuffer();
    let fileReader = new FileReader();

    fileReader.onload = function (e) {
      spark.append(e.target.result);
      currentChunk++;
      if (currentChunk < chunks) {
        loadNext();
      } else {
        let md5 = spark.end();
        resolve(md5);
      }
    };
    fileReader.onerror = function (e) {
      reject(e);
    };

    function loadNext() {
      let start = currentChunk * chunkSize;
      let end = start + chunkSize;
      if (end > file.size) {
        end = file.size;
      }
      fileReader.readAsArrayBuffer(blobSlice.call(file, start, end));
    }
    loadNext();
  });
}

二、设置参数&分片上传代码

const chunkSize = 10 * 1024 * 1024;//定义分片的大小 暂定为10M
function getBase64(img, callback) {
  const reader = new FileReader();
  reader.addEventListener("load", () => callback(reader.result));
  reader.readAsDataURL(img);
}

// 上传前数据验证
beforeUpload(file) {
  // console.log(`beforeUpload`);
  let _continue = true;
  let { name, size } = file;
  name = toLower(name);
  const fileSize = size / 1024 / 1024
  //文件大小(大于100m再分片哦,否则直接走普通文件上传的逻辑就可以了)
  if (fileSize > 100) {
    this.sparkMd5 = true //走大文件
  }else{
    this.sparkMd5 = false //普通上传
  }
},



// 将文件上传到本地,暂时保存
async localFiles(File) {
 let file = File.file;
 let fileList = cloneDeep(this.localFileList),
   maxLength = this.maxLength;
 // 判断当前列表没有重名的附件
 // let isHas = some(fileList, item => item.name === file.name);
 // if (isHas) {
 // 如果重名,退出不继续上传
 //   this.$message.error(`${file.name}已存在!`);
 //   return;
 // }
 // 将需要上传的附件转成getBase64,用来本地预览
 getBase64(file, url => {
   file.url = url;
   file.thumUrl = url;
 });

 //这里只展示 大文件时
 if (this.sparkMd5) {
   let num = 0
   //大文件file 暂存
   this.sparkMd5File.push(file)
   //加载进度条弹出
   this.sparkModalVisible = true
   //文件大小
   const fileSize = file.size
   this.currentFileSize = fileSize
   //计算当前选择文件需要的分片数量
   const chunkCount = Math.ceil(fileSize / chunkSize)
   //每一片所占百分比
   // const progress =  (100 / chunkCount).toExponential(2);
   // console.log(progress);
   // const progress = Math.ceil(100 / chunkCount) toExponential()
   //获取文件md5
   const fileMd5 = await getFileMd5(file, chunkCount,chunkSize);
   // 循环调用上传
     for (var i = 0; i < chunkCount; i++) {
       //分片开始位置
       let start = i * chunkSize
       //分片结束位置
       let end = (i + 1) * chunkSize
       //取文件指定范围内的byte,从而得到分片数据
       let _chunkFile = file.slice(start, end)
       let fileName = new Date().getTime() + "_" + file.name;
       let form = new FormData()
       form.append('file', _chunkFile)
       form.append('type',file.type) //类型
       form.append('chunkNumber', i+1) //第几片
       form.append('chunkSize', chunkSize) //定义分片的大小 暂定为10M
       form.append('currentChunkSize', _chunkFile.size,) //当前片大小
       form.append('identifier', fileMd5) //md5唯一加密
       form.append('filename', i + "_" + fileName) //名称
       form.append('totalChunks', chunkCount) //分片数
       form.append('totalSize', fileSize) //总大小
       // 通过await实现顺序上传
       try {
       		//分片接口 (循环调用)
       		//这是接口 后端接口!!!不是漏写!
           await upLoadChunk(form)
           //百分比显示
           num += (100 / chunkCount).toExponential(2) - 0
           this.progress = num.toExponential(2) - 0
           
       } catch (error) {
           this.sparkModalVisible = false
           this.$message.error("网络错误");
           return
       }
       // return
   }
   // 文件上传完毕,请求后端合并文件并传入参数
   await  this.composeFile(fileMd5, file.name, chunkCount)
 }
},

三、合并文件


    /**
     * 请求后端合并文件
     * @param fileMd5 文件md5
     * @param fileName 文件名称
     * @param count 文件分片总数
     */
    composeFile(fileMd5, fileName, count) {
      this.spinning = true
      var data = {
        "businessType": this.businessType, //业务类型
        "totalSize": this.currentFileSize, //总大小
        "identifier": fileMd5, //文件的md5
        "fileName": fileName, //文件名
        "totalChunks": count //分片的总数量
      }
      //合并接口
      //这是接口 后端接口!!!不是漏写!
      mergeChunk(data).then(res=>{
        this.uploadedIdsTemp.push(res.id)
        this.$message.success("合并成功"); 
        this.sparkModalVisible = false
        this.spinning = false
        this.progress = 0
      })
    },

你可能感兴趣的:(vue,vue.js,javascript,前端)