1、前言

目前的element-ui在上传大文件时会出现上传失败的问题,项目希望实现大文件断点续传,秒传等功能。之前在TP项目下使用webuploader上传插件,文件服务器用PHP编写的。由于久不维护,决定使用vue-simple-uploader实现,文件服务器使用golang编写。

2、安装

npm install vue-simple-uploader --save

main.js引用:

md5工具安装:

npm install spark-md5 --save

在当前目录引用:

3、使用

          <div
            class="upload-box"
            v-if="checkBtnMp4()"
          >
            <div>
              <span class="title">上传视频</span>至多1个,不大于600M,支持格式:MP4
            </div>
            <uploader
              ref="upload"
              class="uploader-example"
              :options="options"
              :autoStart="true"
              :file-status-text="statusText"
              @file-success="success_video"
              @file-added="filesAdded"
              @file-progress="fileProgress"
              @file-error="onFileError"
              @file-removed="videoRemove"
            >
              <uploader-unsupport></uploader-unsupport>
              <uploader-drop>
                <uploader-btn
                  :single="true"
                  :attrs="attrs2"
                >点击上传</uploader-btn>
              </uploader-drop>
              <uploader-list v-show="panelShow"></uploader-list>
            </uploader>
            <ul
              class="el-upload-list el-upload-list--text success-video"
              v-if="show_filename && fileListMp4"
            >
              <li
                tabindex="0"
                class="el-upload-list__item is-success"
                v-for="(item, i) in fileListMp4"
                :key="i"
              >
                <a class="el-upload-list__item-name">
                  <i class="el-icon-video-play"></i>
                  {{item.filename}}
                </a>
                <label class="el-upload-list__item-status-label">
                  <i class="el-icon-upload-success el-icon-circle-check"></i>
                </label>
                <i
                  class="el-icon-close"
                  @click="delMp4()"
                ></i>
              </li>
            </ul>
          </div>
export default {
  name: "XXX",
  data() {
    return {
      isUploadOk: true, // 是否还有未上传完成的文件
      // 视频
      FileLimit: {
        FileMaxSize: 600, // 允许上传的大小 单位(G)
        FileFormat: ["mp4"], // 允许上传的格式
        FileUnit: "M" // 单位
      },
      panelShow: true, // 展示上传panel
      show_filename: true, //是否显示文件列表
      fileListMp4: [], // 视频格式数据
      uploadUrl: "", // 文件上传地址
      uploadData: "", // 文件上传参数
      options: {
        target: url.uploadPath, // 上传地址
        testChunks: false,
        singleFile: true, // 启用单个文件上传。上传一个文件后,第二个文件将超过现有文件,第一个文件将被取消。
        chunkSize: "1048576" * 1, //分块大小 单位(M)
        //下面参数文件服务器验证用
        query: {
          //传参
          UserId: localStorage.getItem("ms_userid"),      
          SessionKey: localStorage.getItem("ms_token"),   
          OS: 4,
          PluginType: 1
        }
      },
      //上传状态
      statusText: {
        success: "上传成功!",
        error: "出错了!",
        uploading: "上传中...",
        paused: "等待中...",
        waiting: "等待中..."
      },
      attrs2: {
        accept: ".mp4"  //允许上传的格式
      }
     };
}

4、上传流程

filesAdded:添加一个文件时的钩子。

       progress:上传中的钩子。

       onFileError:上传错误触发。

      videoRemove:视频移除。

      success_video:成功上传触发方法。

      

    // 添加一个文件时触发
    async filesAdded(file) {
      var FileLimit = this.FileLimit;
      const isFormat = this.checkExtensions(file.name, FileLimit.FileFormat); // 文件格式判断
      if (!isFormat) {
        file.ignored = true; // 过滤文件
        file.cancel(); // 停止上传
        return false;
      }

      // 文件大小判断
      const isSize = this.checkSize(file.size);
      if (!isSize) {
        file.ignored = true; // 过滤文件
        file.cancel(); // 停止上传
        return false;
      } else {
        this.panelShow = true; // 展示上传panel
        this.show_filename = false; // 不显示文件名
        this.computeMD5(file); // md5验证
      }
    },
    // 检查文件大小
    checkSize(fileSize) {
      var FileLimit = this.FileLimit;
      var isSize = fileSize / 1024 / 1024 < FileLimit.FileMaxSize; // 单位(M)
      if (!isSize) {
        this.$message.warning(
          " 文件大小不能大于" + FileLimit.FileMaxSize + FileLimit.FileUnit + "!"
        );
        return false;
      }
      return true;
    },
    // extensions 允许上传的格式
    checkExtensions(fileName, extensions) {
      var format = fileName
        .split(".")
        .pop()
        .toLowerCase(); // 用户上传的文件格式

      // 把允许上传文件格式的数组转为字符串
      var s = extensions.join(",");
      var exp = new RegExp(format);
      if (!exp.test(extensions)) {
        this.$message.warning("请上传 " + s + " 的格式!");
        return false;
      }
      return true;
    },

    // 文件上传中触发
    fileProgress(rootFile, file, chunk) {
      // 判断上传是否在上传
      if (file.isUploading()) {
        this.isUploadOk = false; // 禁止上传
      } else {
        this.isUploadOk = true; // 允许上传
      }
    },
    // 上传错误触发
    onFileError(rootFile, file, response, chunk) {
      this.$message({
        message: "上传失败,请重新上传!",
        type: "error"
      });
    },
    // 校验MD5
    computeMD5(file) {
      let fileReader = new FileReader();
      let time = new Date().getTime();
      let blobSlice =
        File.prototype.slice ||
        File.prototype.mozSlice ||
        File.prototype.webkitSlice;
      let currentChunk = 0;
      const chunkSize = 10 * 1024 * 1000;
      let chunks = Math.ceil(file.size / chunkSize);
      let spark = new SparkMD5.ArrayBuffer();
      file.pause();

      loadNext();

      fileReader.onload = e => {
        spark.append(e.target.result);
        if (currentChunk < chunks) {
          currentChunk++;
          loadNext();
          this.$nextTick(() => {});
        } else {
          let md5 = spark.end();
          this.computeMD5Success(md5, file);
        }
      };
      fileReader.onerror = function() {
        this.error(`文件${file.name}读取出错,请检查该文件`);
        file.cancel();
      };

      function loadNext() {
        let start = currentChunk * chunkSize;
        let end =
          start + chunkSize >= file.size ? file.size : start + chunkSize;
        fileReader.readAsArrayBuffer(blobSlice.call(file.file, start, end));
      }
    },
    // 验证成功
    computeMD5Success(md5, file) {
      file.uniqueIdentifier = api.randomString(32); //把md5值作为文件的识别码
      file.resume(); //开始上传
    },
    // 视频移除
    videoRemove(file, fileList) {
      this.fileListMp4 = [];
    },
    // 成功上传触发方法
    success_video: function(rootFile, file, response, chunk) {
      var response = JSON.parse(response);
      if (response.Result) {
        const fileLists = [];
        fileLists.push(response.Data);
        this.fileList = fileLists;
      } else {
        this.$message.error(response.Errstr);
        return false;
      }
    },

 

 

 

 

 

Logo

前往低代码交流专区

更多推荐