前端 - vue - - elementui上传文件组件封装

06-01 1064阅读

场景:

在大多数的后台管理系统开发中 都会有上传文件/图片的操作 后端需要我们传file或者formdata对象 我们可以基于elementui的upload控件实现(大多数ui库的实现原理相同)

elementui的upload控件提供了各种配置 我们需要用到的有 list-type(文件列表表现类型)、file-list(绑定的文件数据)、limit(限制上传个数)、accept(限制上传类型)、before-upload(上传前的回调)、http-request(自定义上传)、on-remove(移除时的回调)、v-loading(加载中效果 看需求而定)【点击跳转至elementui upload控件官方文档】

html:

    
    
      点击上传
    
      
        文件类型为
        {{ accept }}
        
        ,最多上传{{ limit }}个文件
        
        ,且不超过 {{ fileSize }}M
        
        
          (建议图片长为{{ fileDimension[0] }}px, 宽为{{ fileDimension[1] }}px)
        
      
    
      
    

js:

// 封装为公共组建的传值配置
props: {
    // 最大上传数量
    limit: {
      default: () => 1,
      type: [Number, String],
    },
    // 上传文件\图片
    listType: {
      //text/picture/picture-card
      type: String,
      default: () => "text",
    },
    // 上传文件类型
    accept: {
      type: String,
    },
    // 文件大小 单位为M
    fileSize: [Number, String],
    // 图片长宽比 如:长2 宽1 及为2
    fileDimension: Array,
    // 动态接口地址
    MinioUrl: {
      default: () => "sport",
    },
  },
  data() {
    return {
      fileList: [], // 绑定的值
      dataList: [], // 处理删除的值
      isLoading: false, // 加载效果
    };
  },
  created() {},
  computed: {
    // 动态class 判断是否达到最大个数限制
    disabledTwo() {
      return this.fileList.length  this.fileSize * 1024 * 1024) {
          this.$message.error("文件过大,请重新选择");
          return false;
        }
      }
      // 尺寸 可强制限制 也可不限制
      // if (this.fileDimension) {
        // 转base64后获取图片大小
      //   fileToBaser64(file, (img) => {
      //     const res = (img.width / img.height).toFixed(1);
      //     if (res === this.fileDimension) return false;
      //  });
      // }
      return true;
    },
    // 移除图片
    async handleRemove(file) {
      // 处理未上传图片但数据回显情况
      if (!this.dataList.length) this.dataList = this.fileList;
      const i = this.dataList.findIndex((ele) => ele.url === file.url);
      const urlArr = this.dataList[i].url.split("/");
      // 编辑记录中删除图片需要同步更新记录中存储图片的字段
       await removeFileApi(
         this.MinioUrl,
         urlArr[urlArr.length - 2] + "/" + urlArr[urlArr.length - 1]
       );
      this.dataList.splice(i, 1);
      this.fileList.splice(i, 1);
      // 返回给父组件值 便于进行保存操作
      this.$emit("fileUploadChange", this.dataList);
    },
    // 上传
    async handleUpload(val) {
      this.isLoading = true;
      // 接口要求formdata对象 初始化formdata并添加值
      const formdata = new FormData();
      formdata.append("file", val.file);
      try {
        const { data } = await uploadFileApi(this.MinioUrl, formdata);
        const fileItem = {
          uid: val.file.uid,
          url: data,
          name: val.file.name,
        };
        // 更新 dataList
        this.dataList.push(fileItem);
        // 检查 fileList 中是否已存在相同文件
        const isDuplicate = this.fileList.some(
          (item) => item.uid === fileItem.uid || item.name === fileItem.name
        );
        if (!isDuplicate) {
          this.fileList.push(fileItem);
        }
        // 更新 fileList
        // this.fileList.push(fileItem);
        // 通知父组件文件上传变化
        this.$emit("fileUploadChange", this.dataList, val.file.name);
      } catch (error) {
        console.error("文件上传失败:", error);
        this.$message.error("文件上传失败,请稍后再试");
      } finally {
        this.isLoading = false;
      }
    },
  },

获取图片尺寸的方法:

// file转base64 原理就是转为base64渲染在img标签中获取宽高
export const fileToBaser64 = (file, callback) => {
  var reader = new FileReader();
  reader.onload = function (event) {
    var base64 = event.target.result;
    var img = document.createElement("img");
    img.src = base64;
    img.onload = function () {
      callback(img);
    };
  };
  reader.readAsDataURL(file);
};

css:

// 控制上传按钮隐藏
.noUpload {
  ::v-deep .el-upload {
    display: none !important;
  }
  ::v-deep .el-upload--picture-card {
    display: none !important;
  }
}

选择图片后立即上传会有两个问题:

1、用户上传图片后 不保存信息 那么这个图片就会占用服务器资源 

2、用户移除图片后 未保存信息并且刷新页面 图片依旧会渲染出来 但根据路径访问图片却访问不到 服务器中也不存在该图片 解决办法:

二者共同的解决方法:

1、后端写定时任务,定时清理服务器中存在但不存在与表中的图片;

2、点击保存按钮后再走上传接口;

此文章只考虑小文件上传 大文件用常规上传方法会很慢导致接口超时 也有可能导致接口奔溃

前端 - vue - - elementui上传文件组件封装
(图片来源网络,侵删)
前端 - vue - - elementui上传文件组件封装
(图片来源网络,侵删)
前端 - vue - - elementui上传文件组件封装
(图片来源网络,侵删)
免责声明:我们致力于保护作者版权,注重分享,被刊用文章因无法核实真实出处,未能及时与作者取得联系,或有版权异议的,请联系管理员,我们会立即处理! 部分文章是来自自研大数据AI进行生成,内容摘自(百度百科,百度知道,头条百科,中国民法典,刑法,牛津词典,新华词典,汉语词典,国家院校,科普平台)等数据,内容仅供学习参考,不准确地方联系删除处理! 图片声明:本站部分配图来自人工智能系统AI生成,觅知网授权图片,PxHere摄影无版权图库和百度,360,搜狗等多加搜索引擎自动关键词搜索配图,如有侵权的图片,请第一时间联系我们。

相关阅读

目录[+]

取消
微信二维码
微信二维码
支付宝二维码