视频(大文件)分片上传

话不多说直接上代码

import http from "./http";
import { BASE_URL } from "./common";
import { Loading } from "element-ui";

var percent = 0;
//视频分片上传方法封装,也适用于大图片
export async function uploadVedio(file) {
  return new Promise((resolve, reject) => {
    console.log("fileeee", file);
    let duration = "",
      title = file.name,
      time = +new Date();
    let url = URL.createObjectURL(file);
    let audioElement = new Audio(url);
    audioElement.addEventListener("loadedmetadata", _event => {
      duration = Math.round(audioElement.duration);
    });
    let pz = {
      maxSize: 1024 * 1024 * 2000, //文件大小限制20M
      bufferSize: 1024 * 512, //单个分片大小
      blocks: [], //分片数据集合
      blockName: "newfile", //表单 file 的名字
      filename: "", //上传的本地文件真实文件名
      threadNum: 10, //上传线程数量
      reset: function(fname) {
        this.blocks = [];
        this.filename = fname;
      }
    };
    let upload_index = 0;
    let upload_activeThreadCount = 0; //当前活跃线程数量
    let upload_sendedBlockCount = 0; //已上传的block数量
    afterselect(file);
    async function afterselect(file) {
      // if (document.getElementById("x").files.length < 1) {
      //   return false;
      // }
      // var file = document.getElementById("x").files[0];
      //限制文件大小
      // if (file.size > this.pz.maxSize) {
      //   this.showmsg(
      //     "文件大小限制:" + this.pz.maxSize + ",实际文件大小:" + file.size
      //   );
      //   return;
      // }
      pz.reset(file.name);

      upload_index = upload_activeThreadCount = upload_sendedBlockCount = 0;

      var endByte = 0,
        startByte = 0;

      while (true) {
        startByte = endByte;
        if (endByte + pz.bufferSize >= file.size) {
          endByte = file.size;
        } else {
          endByte = endByte + pz.bufferSize;
        }
        var block = sliceFile(file, startByte, endByte);
        if (!block) {
          console.log("分片失败");
          return;
        }
        pz.blocks.push(block);
        if (endByte >= file.size) {
          break;
        }
      }

      var dis = Math.min(pz.threadNum, pz.blocks.length);
      for (var i = 0; i < dis; i++) {
        (i => {
          setTimeout(async () => {
            upload_activeThreadCount++;
            fenpei(i);
          }, 500);
        })(i);
      }
    }

    //只要是操作主线程中的变量或其他,就一定会自动同步到主线程来。相当于自动lock()
    async function fenpei(i) {
      //参数:线程名
      if (upload_index >= pz.blocks.length) {
        upload_activeThreadCount--;
        if (upload_activeThreadCount == 0) {
          combineFile();
        }
        return;
      }
      uploadBlock(i, upload_index);
      upload_index++;
    }
    //发送拼接分块命令
    async function combineFile() {
      var fd1 = new FormData();
      fd1.append("act", "combine"); //文件
      fd1.append("chunks", pz.blocks.length); //文件名
      fd1.append("filename", pz.filename); //分片索引
      fd1.append("time", time);
      const res = await http.post("/home/upload/upVideo", fd1);
      resolve(res.data.url);
    }
    //显示进度
    function showPercent() {
      percent = parseInt((upload_sendedBlockCount / pz.blocks.length) * 100);
      // console.log("percent", percent);
      if (percent > 100) {
        percent = 100;
      }
    }
    //上传一个分片
    async function uploadBlock(i, index) {
      var chunk = index;
      var fd = new FormData();
      fd.append("newfile", pz.blocks[chunk]); //文件
      fd.append("filename", pz.filename); //文件名
      fd.append("chunk", chunk); //分片索引
      fd.append("time", time);
      fd.append("chunks", pz.blocks.length); //分片总数
      let config = {
        headers: {
          "Content-Type": "multipart/form-data"
        }
      };
      http
        .post("/home/upload/upVideo", fd, config)
        .then(() => {
          console.log("单个分片", "chunk", chunk);
          upload_sendedBlockCount++;
          showPercent();
          fenpei(i);
        })
        .catch(async e => {
          console.log("出错了", e, "chunk", chunk);
          var fd2 = new FormData();
          fd2.append("newfile", pz.blocks[chunk]); //文件
          fd2.append("filename", pz.filename); //文件名
          fd2.append("chunk", chunk); //分片索引
          fd2.append("time", time);
          fd2.append("chunks", pz.blocks.length); //分片总数
          let config = {
            headers: {
              "Content-Type": "multipart/form-data"
            }
          };
          const res = await http.post("/home/upload/upVideo", fd2, config);
          upload_sendedBlockCount++;
          showPercent();
          fenpei(i);
          console.log("重新上传成功", "chunk", chunk);
        });
    }
    //分割file成分片
    function sliceFile(file, startByte, endByte) {
      if (file.slice) {
        return file.slice(startByte, endByte);
      }
      if (file.webkitSlice) {
        return file.webkitSlice(startByte, endByte);
      }
      if (file.mozSlice) {
        return file.mozSlice(startByte, endByte);
      }
      return null;
    }
  });
}

使用方法
在你需要的页面引入

import { uploadVedio } from "@/util/upload.js";

async changeUploadZip(e) {
      let name = e.target.files[0].name;
      //判断文件格式
      if (!name.endsWith("zip") && !name.endsWith("rar")) {
        this.$message.warning("请上传rar或者zip格式的文件");
        return false;
      }
      this.zipName = e.target.files[0].name;
      this.loadingZip = true;
      //调用分片上传
      let path = await uploadVedio(e.target.files[0], 1);
      this.loadingZip = false;
      this.ruleForm.zip = path;
    },
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

weixin_42538504

觉得可以的支持一下

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值