上传大文件切片+MD5文件加密,文件上传时对临时文件内容进行加密

此代码为写项目中遇到的,需要的可以直接复制参考使用。

 上传视频时因视频文件过大,所以需要使用分片来进行上传并MD5校验,改到前端校验后在上传,同时改为切片上传,

需要使用md5对文件的临时文件内容加密,和后端的文件相互验证文件

第一步:md5下载

npm install spark-md5

第二步:引入md5

import SparkMD5 from "spark-md5";

第三步:计算文件的MD5值 ,直接上代码

const generateMd5 = (file) => {
  console.log("fileMD5", file);
  return new Promise((resolve, reject) => {
    const chunkSize = 1024 * 1024; // 1MB 分块读取文件
    const blobSlice =
      File.prototype.slice ||
      File.prototype.mozSlice ||
      File.prototype.webkitSlice;
    const chunks = Math.ceil(file.size / chunkSize);
    let currentChunk = 0;
    const spark = new SparkMD5.ArrayBuffer();
    const fileReader = new FileReader();
    fileReader.onload = function (e) {
      spark.append(e.target.result); // append array buffer
      currentChunk++;
      if (currentChunk < chunks) {
        loadNext();
      } else {
        resolve(spark.end());
      }
    };
    fileReader.onerror = function (err) {
      reject(err);
    };
    function loadNext() {
      const start = currentChunk * chunkSize;
      const end =
        start + chunkSize >= file.size ? file.size : start + chunkSize;
      fileReader.readAsArrayBuffer(blobSlice.call(file, start, end));
    }
    loadNext();
  });
};

 用的是element-plus中的el-upload,因为我是上传视频,所以直接设置accept为:video/*,

进度条用的是:el-progress, 代码如下:

 <el-form-item label="用户视频素材" prop="saved_path">
            <el-upload
              class="upload-demo"
              drag
              accept="video/*"
              :onChange="changeUpload"
              :before-upload="handleBeforeVideoUpload"
              action="#"
              multiple
              :file-list="fileList"
            >
              <div v-if="uploadVideoTip == ''">
                <el-icon class="el-icon--upload">
                  <Plus />
                </el-icon>
                <div class="el-upload__text">点击+号上传或将文件拖拽到框内</div>
              </div>
              <div v-else><el-button>继续上传</el-button></div>

              <template #tip>
                <div
                  class="el-upload__tip"
                  style="display: flex; align-item: center"
                >
                  <span v-if="uploadVideoTip == ''"> *每个大小不得超过1G</span>
                  <span v-else>
                    <el-scrollbar height="40vh">
                      <div v-for="(item, index) in videoFiles" :key="index">
                        {{ item.name }}
                        <img
                          src="../assets/img/取消.png"
                          alt=""
                          @click="delImg(item)"
                        />
                        <el-icon
                          v-if="item.uploaded"
                          style="color: #24b023; font-size: 20px"
                          ><Check
                        /></el-icon>
                      </div>
                    </el-scrollbar>
                  </span>
                </div>
              </template>
            </el-upload>
            <el-progress :percentage="progress" v-show="progress > 0" />
          </el-form-item>

上传视频时,先通过判断文件是否大于20M,如果小于20则正常上传,如果大于20则进行分片来上传,并且MD5是加密切割之前的文件 ,代码如下:


const progress = ref(0); //视频进度

const changeUpload = async (file) => {
  console.log("视频上传file ", file);
  let { name, size, raw: uploadfile } = file;
  let chunkSize = 5 * 1024 * 1024; //默认每个分片为5M 
  // 生成的md5值························································
  let md5FileName = await generateMd5(uploadfile);

//通过判断视频文件,如果大于20M则进行分片,代码如下:

  if (size <= 20 * 1024 * 1024) {
    // 文件小于20M
    let formData = new FormData();
    formData.append("block_id", 1); //默认为1
    formData.append("block_total", 1); //默认为1
    formData.append("saved_path", uploadfile);//视频文件
    formData.append("md5_file_name", md5FileName); //MD5内容加密
    formData.append("saved_path_name", name); //文件名
    agentsUploadsApi(formData).then((res) => {
      console.log("上传res", res.data.data);
      if (res.status !== 200) {
        return;
      } else {
        if (res.data.code == 0) {
          let ids = res.data.data;
          if (ids.result.id) {
            ElMessage({
              message: "上传成功,请提交",
              type: "success",
            });
          }
        } else {
          ElMessage({
            message: res.data.msg,
            type: "error",
          });
        }
      }
    });
  } else {
    // 文件大于20M
    let chunkList = [], startSize = 0;

    while (startSize < size) {
      let endSize = Math.min(size, startSize + chunkSize);
      chunkList.push(uploadfile.slice(startSize, endSize));
      startSize += chunkSize;
    }
    for (let index = 0; index < chunkList.length; index++) {
      let chunk = chunkList[index];
      console.log("分片Blob文件", chunk);

      // 如果分片传入要的是File格式的话,就复制下面注释的这个代码,传splitFile 
      // let blob = new Blob([chunk], { type: uploadfile.type });
      // // 创建新的 File 对象来表示分片,包含文件的后缀名
      // let splitFile = new File(
      //   [blob],
      //   name.slice(0, name.lastIndexOf(".")) +
      //     index +
      //     name.slice(name.lastIndexOf(".")),
      //   { type: uploadfile.type }
      // ); 

      let formData = new FormData();
      formData.append("block_id", index + 1); //当前上传的第几块
      formData.append("block_total", chunkList.length);//总分片数
      formData.append("saved_path", chunk); //将分片传入 这是blob格式
      formData.append("md5_file_name", md5FileName);  //MD5内容加密
      formData.append("saved_path_name", name); //文件名
      //调取接口  上传为异步并使用await等待其完成
      let response = await agentsUploadsApi(formData);
      console.log("上传res", response.data.data);
      if (response.status !== 200) {
        return;
      }
      if (response.data.code == 0) {
        let ids = response.data.data;
        if (ids.result.id) {
          ElMessage({
            message: "上传成功,请提交",
            type: "success",
          });
        }
        progress.value = Math.round(((index + 1) / chunkList.length) * 100);//视频上传进度
      } else {
        ElMessage({
          message: response.data.msg,
          type: "error",
        });
      }
    }
  }
};

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值