vue+ElementUI上传图片等文件

关于vue+ElementUI中上传图片、视频或者文本文件等资源时,可以使用一个强大的组件来实现,下面直接上代码:

<template>
  <div v-loading="loading" element-loading-text="文件上传中,请勿操作">
    <el-upload
      class="upload-demo"
      ref="upload"
      :action="action"
      :file-list="fileList"
      :on-success="uploadSuccess"
      :http-request="uploadFile"
      :on-error="uploadError"
      :disabled="!canUploadFile"
      :on-remove="uploadRemove"
      :on-change="uploadChange"
      :accept="accept"
      :multiple="multiple"
    >
      <el-button
        slot="trigger"
        size="small"
        type="primary"
        :disabled="!canUploadFile"
        >上传文件</el-button
      >

      <div slot="tip" class="el-upload__tip">
        <el-button
          slot="trigger"
          size="small"
          type="primary"
          @click="clearUploadList"
          >清空已上传文件</el-button
        >
        <el-progress :percentage="percentageNumber"></el-progress>
      </div>
    </el-upload>
  </div>
</template>

<script>
import {
  postAetheruploadInit,
  postAetheruploadUpload,
} from "@/api/game/aid.js";
export default {
  data() {
    return {
      action: "",
      percentageNumber: 0,
      fileList: [],
      uploadName: "",
      successUploadList: [],
      loading: false,
    };
  },
  props: {
    // 可上传的文件个数 -1 为可以无限上传 不能为0
    limit: {
      type: Number,
      default: 1,
    },
    // 限制上传的格式
    accept: {
      type: String,
      default: "",
    },
    multiple: {
      type: Boolean,
      default: false
    }
  },
  created() {
    if (this.limit === 0) {
      throw Error("上传文件限制不能为0");
    }
  },
  computed: {
    canUploadFile: {
      get() {
        return this.limit === -1 || this.limit > this.successUploadList.length;
      },
    },
  },
  methods: {
    uploadError() {
      this.loading = false;
      this.clearUploadList();
    },
    isUploading() {
      let res = false;
      if (this.percentageNumber > 0 && this.percentageNumber < 100) {
        this.$message.error("文件上传中,请勿关闭");
        res = true;
      }
      return res;
    },
    uploadChange(file, fileList) {
      this.fileList = fileList
    },
    async uploadFile(data) {
      /*
        记录一个elementui上传组件的坑
        如果在这个函数中有报错它是不会被控制台所监控的  
        因为在这是一个加了async关键字的函数 async会将这个函数污染成一个Promise状态的函数
        在upload组件内部应该有自己的对应Promise的catch机制 并且不会抛出到控制台上
        所以当不出效果的时候就要去掉async 或者用try catch去自己捕获错误 而不使用elementui的错误机制
        或者把async去掉改写成then catch的写法
        补充一句纯函数才是yyds
      */
      // 第一步先文件上传初始化
      this.loading = true;
      let { file } = data;
      try {
        let res = await postAetheruploadInit({
          file_name: file.name,
          file_size: file.size,
        });
        let { chunkSize, uploadBasename, uploadExt } = res;
        let start = 0; // 每次上传的开始字节
        let end = start + chunkSize; // 每次上传的结尾字节
        let chunks = [];
        let type = file.type;
        while (start < file.size) {
          // 根据长度截取每次需要上传的数据
          // File对象继承自Blob对象,因此包含slice方法
          let blob = file.slice(start, end, type);
          chunks.push(blob);
          start = end;
          end = start + chunkSize;
        }
        // 循环发请求
        let temp = 0;
        for (let i = 0; i < chunks.length; i++) {
          let item = chunks[i];
          let formData = new FormData();
          formData.append("file", item);
          formData.append("upload_ext", uploadExt);
          formData.append("chunk_total", chunks.length);
          formData.append("chunk_index", i + 1);
          formData.append("upload_basename", uploadBasename);
          await postAetheruploadUpload(formData)
            .then((res) => {
              temp++;
              this.percentageNumber = parseInt((temp / chunks.length) * 100);
              if (res.uploadName) {
                this.uploadName = res.uploadName;
                this.successUploadList.push(this.uploadName);
                this.$message.success("上传成功");
              }
            })
            .catch((err) => {
              // 如果上传失败  就清空进度条并且清空上传列表
              this.clearUploadList();
              this.$message.error("上传失败" + err);
            });
        }
        if (this.canUploadFile) {
          // 如果可以上传多个就清空进度条
          // 清空列表和进度条状态
          this.percentageNumber = 0;
        }
      } catch (error) {
        this.clearUploadList();
        this.$message.error("上传失败" + error);
      }
      this.loading = false;
    },
    uploadSuccess() {
      this.$emit("uploadSuccess", this.uploadName);
    },
    uploadRemove(file, fileList) {
      this.$emit("uploadRemove", file, fileList)
    },
    clearUploadList() {
      // 清空列表和进度条状态
      this.percentageNumber = 0;
      this.$refs.upload.clearFiles();
      this.uploadName = "";
      this.successUploadList = [];
      // 把空的name传出去
      this.uploadSuccess();
      // 触发清空事件
      this.$emit("uploadClear")
    },
  },
};
</script>

<style>
</style>

说明:在使用这个组件的时候需要进行传值,大家可以先看看这个组件的代码再进行使用,传值也是非常简单的,如果不会的话可以去学习一下我之前发的有关vue传值的博客。

  • 0
    点赞
  • 7
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值