华为云obs切片上传封装 结合vue2 element upload 带有进度条

<template>
  <div>
    <el-upload class="avatar-uploader" action :show-file-list="false" :http-request="handleUpload" :disabled="disabled || loading">
      <slot>
        <el-button :disabled="disabled" type="primary" :loading="loading">
          <slot name="text">上传APK</slot>
        </el-button>
      </slot>
    </el-upload>
    <el-progress v-if="loading" class="mt10" :text-inside="true" :stroke-width="20" :percentage="percentage" />
    <div v-if="parsing" style="color:#f56c6c">上传完成,正在解析,请稍后...</div>
  </div>
</template>
 
<script>
import ObsClient from "esdk-obs-browserjs/src/obs";
import request from "@/config/serve.js"; // 导入已经封装的请求方法 这里根据你自己的请求方法来修改和使用
export default {
  props: {
    expandData: {}, // 其他附加数据
    // 是否禁用
    disabled: {
      type: Boolean,
      default: false,
    },
  },
  data() {
    return {
      url: "",
      initiateData: {
        option: {},
        uploadId: "",
      },
      fileName: "",//上传的文件名
      fileUrl: "",//上传到华为云的文件路径
      obsClient: null,
      loading: false,// 整个上传是否完成
      parsing: false,// 上传完成,正在解析包体
      Bucket: "yourBucket",// 桶名
      obsUrl: "yourObsUrl",//拼接地址
      percentage: 0,//文件上传进度
      fileSize: "",// 文件大小

    };
  },
  methods: {
    async handleUpload(option) {
      const isUpload = await this.beforeUpload(option.file);
      if (!isUpload) return;
      await this.getObsClient();
      this.loading = true;
      const _this = this;
      this.initiateData.option = option;
      let _fileName = option.file.name; // 文件名
      const fileSuffixIndex = _fileName.lastIndexOf("."); // 找到文件后缀名的位置
      _fileName = `${_fileName.substring(0, fileSuffixIndex)}_${new Date().getTime()}${_fileName.substring(fileSuffixIndex)}`; // 添加时间戳
      this.fileName = _fileName;
      this.fileUrl = "market/apk/" + _fileName; // 路径 + 文件名 market/apk为案例 根据你的实际情况而定
      const params = {
        Bucket: this.Bucket, // 桶名
        Key: this.fileUrl,
      };
      this.obsClient.initiateMultipartUpload(params).then((result) => {
        if (result.CommonMsg.Status < 300) {
          const uploadId = result.InterfaceResult.UploadId;
          _this.initiateData.uploadId = uploadId;
          /*
           * Step 2: upload a part
           */
          const etag = [];
          const uploadPromise = new Promise((resolve) => {
            this.fileSize = option.file.size;
            const partLen = 200 * 1024 * 1024;// 分片大小
            const count = Math.ceil(option.file.size / partLen);
            const indexNum = 0;
            this.uploadPartMethod(option, uploadId, indexNum, partLen, etag, count, resolve);
          });
          uploadPromise.then((result) => {
            const paramsEnd = {
              Bucket: this.Bucket,
              Key: this.fileUrl,
              UploadId: uploadId,
              Parts: etag.sort((a, b) => a.PartNumber - b.PartNumber),
            };
            this.obsClient.completeMultipartUpload(paramsEnd).then((result) => {
              if (result.CommonMsg.Status < 300) {
                const url = this.obsUrl + this.fileUrl; //返回访问链接
                this.url = url;
                const obj = {
                  accessPath: url,
                  fileName: this.fileName,
                  suffix: "apk",
                };
                this.getApkInfo(obj);
              }
            });
          });
        }
      });
    },
    async beforeUpload(file) {
      let isFileType = true
      const fileName= file.name;
      const fileType = fileName.substring(fileName.lastIndexOf(".") + 1).toLowerCase();
      isFileType = ["apk"].includes(fileType);
      if (!isFileType) {
        this.$message.error(`上传文件只能是 apk 格式!`);
      }
      // 文件名只含有大小写字母、数字、下划线、-、中文.
      var regex=/^[A-Za-z0-9_\-\.\u4e00-\u9fa5]+$/ig;
      const isLegalName = regex.test(fileName);
      if(!isLegalName){
        this.$message.error("上传的文件只能由大小字母、数字、下划线、中文组成");
      }
      return isFileType && isLegalName;
    },
    uploadPartMethod(option, uploadId, indexNum, partLen, etag, count, resolve) {
      const _this = this;
      console.log('正在上传分片', indexNum + 1, count);
      this.obsClient.uploadPart({
        Bucket: this.Bucket,
        Key: this.fileUrl,
        UploadId: uploadId,
        PartNumber: indexNum + 1,
        SourceFile: option.file,
        PartSize: partLen,
        Offset: partLen * indexNum,
        ProgressCallback: function (transferredAmount, totalAmount, totalSeconds) {
          // 获取上传平均速率(KB/S)
          // console.log(transferredAmount * 1.0 / totalSeconds / 1024);
          // 已上传的文件大小
          const preSize = partLen * indexNum + transferredAmount
          // 获取上传进度百分比
          _this.percentage = Math.ceil(preSize * 100 / _this.fileSize)
        }
      }).then((result) => {
        etag.push({
          ETag: result.InterfaceResult.ETag,
          PartNumber: indexNum + 1,
        });
        indexNum++;
        if (indexNum < count) {
          _this.percentage = Math.ceil((indexNum / count) * 100);
          option.file.percent = _this.percentage;
          option.onProgress(option.file);
          _this.uploadPartMethod(option, uploadId, indexNum, partLen, etag, count, resolve);
        }
        if (indexNum == count) {
          _this.percentage = 100;
          option.file.percent = _this.percentage;
          option.onProgress(option.file);
          resolve("任务完成");
          this.percentage = 100
        }
      });
    },
    async getObsClient() {
      const res = await request("请求方法", "你的接口地址", {}, false);
      const hwSecret = res.data.credential;
      this.obsClient = new ObsClient({
        access_key_id: hwSecret.access,
        secret_access_key: hwSecret.secret,
        security_token: hwSecret.securitytoken,
        server: "yourServer",
      });
    },

    // 获取上传apk信息
    async getApkInfo(params) {
      this.parsing = true;
      try {
        const res = await request("请求方法", "你的接口地址", params, false);
        if (res && res.code === 0) {
          const data = res.data;
          this.$emit("success", data);// 上传成功,返回数据
        }
        this.loading = false;
        this.parsing = false;
        this.percentage = 0
      } catch (err) {
        this.loading = false;
        this.parsing = false;
        this.percentage = 0
      }
    },
    // 暴露给父组件校验组件文件是否正在上传
    getValidate(showMsg = true) {
      if (this.loading) {
        if (showMsg) {
          this.$message.error("文件正在上传,请稍后;");
        }
        return false;
      }
      return true;
    },
  },
};
</script>

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值