• 文档、视频、图片上传(点击、拖拽、批量导入)要‍‍‍‍怎么实现?!


    @

    Excel上传和图片视频上传

    Excel上传

    excel的上传其实分为两步:

    1、下载excel模板

    2、上传excel模板

    在项目中涉及到excel的业务,基本上都要先下载excel模板,用户根据下载的模板填写excel信息,然后将信息上传到后台。下面就这两部分别说明:

    1、下载excel模板

    关于下载excel模板的内容请看:调用后台接口实现Excel导出功能以及导出乱码问题解决(👈点击直达)

    2、上传excel模板

    这里用到element 的上传组件,element上传组件提供点击上传和拖动文件上传。

    在这里插入图片描述

    
    
    <script>
    import { getToken } from "@/utils/auth";
    import { isArray } from "min-dash";
    export default {
      name: "ExcelUpload",
      props: {
        uploadData: {
          type: Object,
          default: "",
        },
        actionUrl: {
          type: String,
          default: "",
        },
        acceptType: {
          type: String,
          default: "",
        },
      },
      components: {},
      data() {
        return {
          fileLimit: 1, // 最大值
          headers: {}, // 请求头
          fileInfo: false, // 上传文件
          errorList: [], // 错误列表
          progress: {
            totalFileCount: 0, // 总文件
            handleFileCount: 0, // 上传文件
          },
          fileList: [], // 上传展示的文件列表,如果fileLimit = 1,该数组只能有一个成员
        };
      },
      created() {
        this.headers["Authorization"] = "Bearer " + getToken(); // 获取请求头信息
      },
      methods: {
        onSuccess(response, file, fileList) {
          if (response.code == 200) {
            if (Array.isArray(response.data)) {
              if (response.data.length > 0) {
                this.fileInfo = true;
                file.status = "error";
                this.errorList = [];
                this.errorList.push(...response.data);
                this.$message.error(`操作失败`);
              } else {
                this.$emit("uploadBack");
              }
            } else {
              this.$emit("uploadBack");
            }
          } else {
            this.errorList = [];
            this.errorList.push({
              fileName: '',
              error: response.msg
            });
            this.fileInfo = true;
            file.status = "error";
            this.$message.error(`${response.msg}`);
          }
        },
        onError(err, file, fileList) {
          file.status = "error";
          this.$message.error(`${err.msg}`);
        },
        handleExceed(files, fileList) {
          this.$message.warning(`上传文件数超出限制`);
        },
        onProgress(event, file, fileList) {},
        beforeRemove(file, fileList) {
          this.$confirm("确定移出吗?", "提示", {
            confirmButtonText: "确定",
            cancelButtonText: "取消",
            type: "warning",
          })
            .then(() => {
              this.fileList = [];
              this.fileInfo = false;
              this.errorFile = false;
            })
            .catch(() => {
              fileList.push(file);
            });
        },
      },
      mounted() {},
      watch: {},
      computed: {},
      filters: {},
    };
    script>
    
    

    这里是将element的上传组件进行二次封装,该组件的职责就是负责接受上传的文件、上传地址、上传类型,做通用化处理,在任何需要上传功能的页面引入即可使用,下面将组件拆开来讲:

        <el-upload
          class="upload-demo"
          ref="upload"
          drag
          :data="uploadData"
          :action="actionUrl"
          :accept="acceptType"
          :headers="headers"
          :limit="fileLimit"
          :on-exceed="handleExceed"
          :file-list="fileList"
          :before-remove="beforeRemove"
          :on-progress="onProgress"
          :on-success="onSuccess"
          :on-error="onError"
        >
          <i class="el-icon-upload">i>
          <div class="el-upload__text">将文件拖到此处,或<em>点击上传em>div>
        el-upload>
    

    :data :element的上传组件允许我们在上传的时候携带上传参数,这里的 :data 就是上传携带的参数,该参数由父组件提供(主要业务),这样就可以在多种不同情况下使用,避免参数固定化。

    :action:请求地址,这个请求地址就是后台的接口,但是这个接口不能直接使用,需要在接口前加 process.env.VUE_APP_BASE_API 来判断当前的运行环境。

    :acceptType: 接受文件的类型,例如这里上传 .xlsx 文件,那么点击上传的时候,只会读取系统里 .xlsx 的文件。该类型也是由父页面提供,这样可以区分多种文件上传情况,该组件可以适配多种文件类型,例如: .jpg.png.xlsx.mp4等。

    :headers:请求头,需要加上token才能成功上传。

          :limit="fileLimit"
          :on-exceed="handleExceed"
          :file-list="fileList"
          :before-remove="beforeRemove"
          :on-progress="onProgress"
          :on-success="onSuccess"
          :on-error="onError"
    

    这些就是组件的一些事件以及属性,根据element文档阅读即可,这里带一下:

    limit:最大上传文件数

    on-exceed:上传文件超出最大数时的钩子,可以做错误提示

    file-list:上传文件的数组

    before-remove:上前的事件

    on-progress: 上传中的事件,该事件在上传过程中会持续调用,可以用来做进度条展示。

    on-success:上传成功的事件,当接口返回200,触发该事件。

    on-error: 上传失败的事件,当接口返回500,触发该事件。


    页面中的使用

          <ExcelUploadList
            @uploadBack="uploadBack"
            :acceptType="acceptType"
            :actionUrl="actionUrl"
            :uploadData="uploadData"
          >ExcelUploadList>
    
    export default {
      props: {
        area: Object,
        allArea: Object,
      },
      data() {
        return {
          acceptType: ".zip", // 上传文件类型
          uploadData: {}, // 上传附加的参数信息
          // 文件上传的接口
          actionUrl: `${process.env.VUE_APP_BASE_API}/data/loadExcel/importZip`, 
        };
      },
      methods: {
        uploadBack(response) {
          // 上传成功后触发事件
          this.$message.success(`操作成功`);
          // this.getList(); 刷新列表
        },
    
        onImport() {
          if (!this.area.id) {
            return this.$message.warning("请选择地区");
          }
          this.uploadData = {
            fiProvinceCode: this.allArea.fiProvinceCode, // 省 
            fiCityCode: this.allArea.fiCityCode, // 市
            fiAreaCode: this.allArea.fiAreaCode, // 区
            fiSubdistrictId: this.allArea.fiSubdistrictId, // 街道
            fiCommunityId: this.allArea.fiCommunityId, // 社区
          };
        },
    
      },
      created() {},
      activated() {},
      components: {
        ExcelUpload,
      },
    };
    

    通过父组件将自身业务所需的参数传入到上传组件中,具体的上传业务由组件完成,完成后将结果返回给父组件展示或者刷新展示列表。


    图片和视频

    上文中上传excel的组件,其实已经可以用作图片和视频上传了,我们只需要传入对应的图片或视频接口 actionUrl ,然后将对应的上传类型 acceptType:'.mp4' 提供给组件,在选择文件时就只读取.mp4的文件,然后将上传所需的参数 uploadData 提供给组件,那么图片和视频上传就已经完成了。

    上传图片和视频并不需要模板,直接上传即可,所以会比较方便。其实上传文件都是将文件转成file文件或者formData,将文件传给后端即可。

    // file转formData
    function files(file){
       let formData = new FormData();
       formData.append("file", file); // file转formData
       //formData参数传给后端
       ossUpload(formData).then(res=>{
           //....
       })
    }
    

    如果你要在formData上追加参数,只需要:

    let formData = new FormData();
    formData.append("file", file); // file转formData
    formData.append("params1", val1);
    formData.append("params2", val2);
    // .......
    //formData参数传给后端
    ossUpload(formData).then(res=>{
        //....
    })
    

    上传的错误提醒以及逻辑处理

    某些情况下,我们需要对上传文件做逻辑处理,比如上传失败该如何处理、上传成功如何处理、能上传几个文件、将上传文件的列表做删除、上传中的进度处理等,这些逻辑,组件都提供了对应的钩子,如下:

      created() {
        this.headers["Authorization"] = "Bearer " + getToken();
      },
          
      methods: {
        // 上传成功的钩子,某些情况下需要做逻辑处理
        // 上传5个文件,成功3个,失败2个,这个时候需要在这里做上传失败的文件展示
        onSuccess(response, file, fileList) {
          if (response.code == 200) {
              // 如果失败列表为数组证明有上传失败
            if (Array.isArray(response.data)) {
                // 上传失败列表数大于0表示有失败文件
              if (response.data.length > 0) {
                this.fileInfo = true;  // 打开错误列表展示弹窗
                file.status = "error"; // 更改类型,关联css的字体变红
                this.errorList = []; 
                this.errorList.push(...response.data); // 错误列表数据
                this.$message.error(`操作失败`); 
              } else {
                // 如果错误列表为空,则表示全部上传成功
                this.$emit("uploadBack");
              }
            } else {
              // 全部上传成功
              this.$emit("uploadBack");
            }
          } else {
             // 上传失败
            this.errorList = [];
             // 错误列表数据
            this.errorList.push({
              fileName: '',
              error: response.msg
            });
            this.fileInfo = true; // 打开错误列表展示弹窗
            file.status = "error"; // 更改类型,关联css的字体变红
            this.$message.error(`${response.msg}`);
          }
        },
            
        // 上传失败的钩子
        onError(err, file, fileList) {
          file.status = "error"; // 更改类型,关联css的字体变红
          this.$message.error(`${err.msg}`);
        },
            
        // 上传文件数超出限制的钩子
        handleExceed(files, fileList) {
          this.$message.warning(`上传文件数超出限制`);
        },
            
        // 进度条钩子
        onProgress(event, file, fileList) {},
            
        // 点击移出上传文件的钩子
        beforeRemove(file, fileList) {
          this.$confirm("确定移出吗?", "提示", {
            confirmButtonText: "确定",
            cancelButtonText: "取消",
            type: "warning",
          })
            .then(() => {
              // 重置上传文件的列表,这里限制最大上传为 1 ,所以移出就直接重置
              this.fileList = [];
              this.fileInfo = false; // 关闭上传失败的信息弹窗
              this.errorFile = false; // 关闭错误信息弹窗
            })
            .catch(() => {
              fileList.push(file); // 取消则将文件重新添加到列表,不做任何更改。
            });
        },
      },
    
    
    

    上传失败,在文件展示这里将字体变为红色

    
    

    上传进度处理

    element上传组件帮我们关联了上传进度,从发送请求到请求发送成功,其实这个过程只是将file文件转formData请求接口的过程,真实的文件处理进度并不能通过自带的进度条直接展示,需要调用后端的接口获取上传进度,遍历后端提供的上传进度接口,使用定时器,每隔一段时间调用一次,获取最新的上传进度,当上传进度为100%时停止定时器。

    // 上传文件成功的钩子    
    onSuccess(response, file, fileList) {
          if (response.code == 200) {
            this.fileInfo = true;
    
            // 上传进度处理,定时器循环调用
            let times = setInterval(() => {
              tailProgressAPI(this.uploadData).then((res) => {
                // handleFileCount 已处理数量
                // totalFileCount 上传总数
                  
                // 错误文件数大于0,更新错误列表
                if (res.data.uploadFailList.length > 0) {
                  this.errorList = [];
                  this.errorFile = true;
                  this.errorList.push(...res.data.uploadFailList);
                }
                // 处理数 = 上传总数 处理完成
                if (res.data.handleFileCount == res.data.totalFileCount) {
                  // 页面展示处理结果
                  this.progress.totalFileCount = res.data.totalFileCount;
                  this.progress.handleFileCount = res.data.handleFileCount;
                    // 回传上传结果
                  this.$emit("uploadBack", { code: 200, msg: "操作成功" });
                  // 停止定时器
                  clearInterval(times);
                } else {
                  // 处理中
                  // 更新处理结果
                  this.progress.totalFileCount = res.data.totalFileCount;
                  this.progress.handleFileCount = res.data.handleFileCount;
                }
              });
            }, 500);
          } else {
            file.status = "error"; // 更改类型,关联css的字体变红
            this.$message.error(`${response.msg}`); // 提示错误信息
          }
        },
    

    动态表单-根据配置字段一键生成表单 (👈点击直达)
    element table列表根据数据设置背景色 (👈点击直达)
    css绘制一个Pinia小菠萝(👈点击直达)
    再也不用担心组件跨层级的数据共享和方法驱动了 (👈点击直达)

    如果觉得这篇文章对你有帮助,欢迎点赞👍、收藏💖、转发✨哦~

  • 相关阅读:
    【二】建造者(Builder)模式
    Machine Learning Pre-Basics
    (八)Vue3-huohuo-admin src构建-上
    基于php的校园公寓管理系统设计与实现
    MatrixOne 支持多样化生态工具
    关于小程序session_key漏洞问题的解决2022-12-01
    [PAT练级笔记] 07 Basic Level 1009
    [oeasy]python0012_字符_character_chr函数_根据序号得到字符
    Mongodb实验二——分片集群搭建
    只因说了一句:“反正我有技术,在哪不一样”一位年薪35W自动化测试工程师被某讯开除
  • 原文地址:https://www.cnblogs.com/wang-fan-w/p/17583885.html