elementUi / elementPlus自定义上传方法 Upload自定义文件上传

🚀 个人简介:某大型国企资深软件研发工程师,信息系统项目管理师、CSDN优质创作者、阿里云专家博主,华为云云享专家,分享前端后端相关技术与工作常见问题~

💟 作 者:码喽的自我修养🥰

📝 专 栏:常用组件库与实用工具 🎉

🌈 创作不易,如果能帮助到带大家,欢迎 收藏+关注 哦**💕**

upload组件的 http-request自定义上传方法

upload组件文档地址https://element-plus.org/zh-CN/component/upload.html

element-ui / elementPlus 中,默认以提供action上传地址的方式上传文件,但如果我们使用七牛或者阿里oss上传文件的话,upload这种默认上传文件的方式就行不通了,因为阿里oss等自定义上传接口,往往都有权限,额外的配置参数等限制,所以我们就需要自定义上传接口啦,好在upload组件提供了http-request属性可以让我们自定义上传api

开始着手实现自定义上传吧

使用方法

页面使用模板部分 upload 组件截图如下
methods 中自定义上传方法js代码截图如下

其中ossUpload为我们传递给 upload 组件的自定义上传方法,ossUploadApi为真正的上传文件数据到服务器的api,到这里,就已经可以触发自定义上传文件函数啦。

关联上传钩子

这里有一个问题,因为对于upload上传组件来说,不仅仅有上传文件,还有上传文件成功 success 和失败 error 钩子,需要我们对上传成功和上传失败做一些处理才行。
在没有自定义上传文件前,这些上传钩子是和上传文件请求接口相关联的。而我们自定义了上传文件操作,所以现在上面的写法是不能主动触发upload组件定义的钩子的。

那么我们怎么把自定义上传api和upload组件的这两个钩子关联起来呢,element-ui / elementPlus 文档上介绍提供了 http-request 属性可以让我们可以自定义上传,没有介绍如何使用,这个时候就要发挥我们码农看源代码的能力啦。通过断点源码找到调用我们自定义上传文件方法的地方,如下图所示

通过截图上面的文字分析,我们添加如下所示代码即可,即添加return 语句 返回 promise 结果 ,(注意,因为ossUploadApi这个接口本身实现的时候返回的就是promise(由自己实现返回promise)),所以添加 return 语句返回即可
同时,通过源码我们也发现,upload组件内部往我们自定的上传方法中传递了一个options参数,其中包含了对upload上传文件 success 成功钩子,error 失败钩子,progress 上传进度钩子,也就是说,其实我们也可以在自定义上传里面主动调用这些钩子以实现相应功能(注意自己调用钩子时候保证回调参数一致)。

回调数据

打印自定义上传方法的回调数据(由upload组件内部传递给我们的数据,通过上面源码分析截图调用 httpRequest 的地方,也可以看到回调数据的)

总结:

  • 通过 http-request 属性可以让我们自定义上传 api 方法
  • 我们有两种方案可以将自定义上传方法和upload内部的文件上传 success,error 钩子关联起来

  ① 自定义上传方法并返回promise (推荐)

  ② 在自定义上传方法中主动调用upload组件提供的钩子或者调用自己定义的钩子

完整代码如下

javascript 复制代码
<template>
  <el-upload
    ref="upload"
    :action="doUpload"
    :headers="headers"
    :http-request="ossUpload"
    :on-preview="handlePictureCardPreview"
    :on-remove="handleRemove"
    :on-success="handleSuccess"
    :on-error="handleError"
    :before-upload="beforeUpload"
    :file-list="fileList"
    :disabled="disable"
  >
    <el-button
      size="small"
      :disabled="disable"
      type="primary"
    >
      上传文件
    </el-button>
    <div
      slot="tip"
      class="el-upload__tip"
    >
      支持jpg、png、pdf、word格式,大小不超过500M。
    </div>
  </el-upload>
</template>

<script>
  import { getToken } from '@/utils/auth';
  import { ossUploadApi } from '@/api/serviceProvider';
  export default {
    name: 'Upload',
    model: {
      prop: 'fileList',
      event: 'change',
    },
    props: {
      fileList: {
        type: Array,
        required: true,
      },
      disable: {
        type: Boolean,
        default: false,
      },
    },
    data() {
      return {
        // 上传地址
        doUpload:
          process.env.VUE_APP_BASE_API +
          (process.env.NODE_ENV === 'production' ? '' : '/api') +
          process.env.VUE_APP_BASE_CONTENT_URL +
          '/contract/upload',
        // doUpload: 'https://jsonplaceholder.typicode.com/posts/',
        // 下载请求头
        headers: {
          tgt: getToken(),
        },
      };
    },
    watch: {},
    methods: {
      // 处理文件点击预览操作
      handlePictureCardPreview(file) {
        console.log(file);
        let downUrl = '';
        if (file.hasOwnProperty('url')) {
          downUrl = file.url;
        } else {
          downUrl = file.response.message;
        }
        // 赋值
        const a = document.createElement('a');
        // 创建href属性
        a.href = downUrl;
        // 点击下载
        a.click();
      },
      // 上传前
      beforeUpload(file) {
        const limitSize = 500;
        const isLt500M = file.size / 1024 / 1024 < limitSize;
        if (!isLt500M) {
          this.$message.error(`上传文件大小不能超过 ${limitSize}MB!`);
        }
        return isLt500M;
      },
      // 手动删除文件钩子
      handleRemove(_file, fileList) {
        console.log(fileList);
        this.processFileList(fileList);
      },
      // 上传成功钩子
      handleSuccess(_res, _file, fileList) {
        console.log(fileList);
        this.processFileList(fileList);
      },
      // 上传失败的钩子
      handleError(err, _file, fileList) {
        if (err.code !== 200) {
          this.$message({
            message: err.message || '上传失败',
            type: 'warning',
          });
        }
        this.processFileList(fileList);
      },
      // 自定义处理filelist
      processFileList(fileList) {
        fileList.forEach((item) => {
          if (!item.url && item.response) {
            const response = item.response;
            item.url = response.url;
          }
        });
        this.triggerChange(fileList);
      },
      triggerChange(fileList) {
        this.$emit('change', fileList);
      },
      // 自定义上传oss方法
      ossUpload(option) {
        const file = option.file;
        return ossUploadApi(file);
      },
    },
  };
</script>
<style lang="scss" scoped></style>

到此这篇文章就介绍到这了,更多精彩内容请关注本人以前的文章或继续浏览下面的文章,创作不易 ,如果能帮助到大家,希望大家点点收藏+关注~💕

更多专栏订阅推荐:

🥕 JavaScript深入研究

👍 前端工程搭建

💕 vue从基础到起飞

✈️ HTML5与CSS3

🖼️ JavaScript基础

⭐️ uniapp与微信小程序

📝 前端工作常见问题与避坑指南

✍️ GIS地图与大数据可视化

📚 常用组件库与实用工具

💡 java入门到实战

相关推荐
mldong26 分钟前
你的 Vue3 项目也能有钉钉同款审批流设计器:npm 装包,10 分钟画出第一条审批流
前端·vue.js
2分钟速写快排1 小时前
什么是 RAG?如何用 RAG 实现一个用户记忆?
前端·后端·ai编程
passerby60612 小时前
如何自己造一个时间处理库
前端·javascript·github
走到天涯海角3 小时前
react里面的长列表渲染优化
前端·react.js·前端框架
小羊没烦恼!3 小时前
Hello Web API系列教程——Web API与国际化
java·服务器·前端·javascript·php
北岛贰3 小时前
迷茫焦虑期,我做了一个带支付带官网的 AI 聊天虚拟恋人 App
前端·人工智能·后端
mayaairi5 小时前
Vue2 组件通讯(三):全局事件总线、PubSub、插槽与组件实例属性
前端·javascript·vue.js
OpenAnolis小助手5 小时前
一句话看透 JVM,SysOM 诊断 Skill 新增 Java 应用诊断能力
java·开发语言·jvm·阿里云·操作系统控制台·sysom
kyriewen5 小时前
面试官问我:AI 都能写代码了,前端凭什么还值 25K
前端·javascript·人工智能
风骏时光牛马6 小时前
AI源码分析:拆解模型底层实现逻辑
前端