前言

饿了吗UI的上传组件很多朋友都用过,最近用到这个组件后遇到了一些新的问题。特此记录一下。

upload组件参数了解

在饿了吗UI文档中可以了解到他的提供出来的属性,这里有一些参数需要做一些说明。
首先action参数作为必选参数,不管使用哪种方式上传文件都要填写该属性,
headers附带的一些请求头部信息,比如token等等,data上传时附带的一些额外的参数,比如需要的额外的接口入参
accept上传时点击上传按钮调用硬件的api,供用户去本机选择需要上传的文件,这里规定了文件的类型后,用户去选择上传文件时,只能看到可以上传的文件,其他的都将被过滤。
http-request可以自定义上传方法。不用默认的上传方式可以选择该方法。
还有一些钩子,他们都将在文件的各个阶段被触发,前提是你要在组件上添加对应的钩子。

Attribute

参数说明类型可选值默认值
action必选参数,上传的地址string
headers设置上传的请求头部object
multiple是否支持多选文件boolean
data上传时附带的额外参数object
name上传的文件字段名stringfile
with-credentials支持发送 cookie 凭证信息booleanfalse
show-file-list是否显示已上传文件列表booleantrue
drag是否启用拖拽上传booleanfalse
accept接受上传的文件类型(thumbnail-mode 模式下此参数无效)string
on-preview点击文件列表中已上传的文件时的钩子function(file)
on-remove文件列表移除文件时的钩子function(file, fileList)
on-success文件上传成功时的钩子function(response, file, fileList)
on-error文件上传失败时的钩子function(err, file, fileList)
on-progress文件上传时的钩子function(event, file, fileList)
on-change文件状态改变时的钩子,添加文件、上传成功和上传失败时都会被调用function(file, fileList)
before-upload上传文件之前的钩子,参数为上传的文件,若返回 false 或者返回 Promise 且被 reject,则停止上传。function(file)
before-remove删除文件之前的钩子,参数为上传的文件和文件列表,若返回 false 或者返回 Promise 且被 reject,则停止删除。function(file, fileList)
list-type文件列表的类型stringtext/picture/picture-cardtext
auto-upload是否在选取文件后立即进行上传booleantrue
file-list上传的文件列表, 例如: [{name: 'food.jpg', url: 'https://xxx.cdn.com/xxx.jpg'}]array[]
http-request覆盖默认的上传行为,可以自定义上传的实现function
disabled是否禁用booleanfalse
limit最大允许上传个数number
on-exceed文件超出个数限制时的钩子function(files, fileList)-

默认上传

如果我们采用默认的上传方式,

  • 只需要在upload组件上添加action属性,同时将要上传的地址填上去,
  • 如果需要传额外的参数在添加data属性,
  • 文件上传列表需要手动添加,
  • 以及添加一些钩子来处理一些操作
<el-upload
              class="upload-demo"
              :action="uploadUrl"
              :data="{token}"
              :accept="acceptFileTypes"
              :show-file-list="false"
              :before-upload="handleBeforeUpload">
              <el-button size="small" type="primary">上传</el-button>
            </el-upload>

然后使用一些钩子来做近一步处理,

handleBeforeUpload(file) {//上传之前的效验
        if (file.size > 1024*1024*1024) {
          this.$message.warning('文件大小已超出限制,请精简后重试')
          return false
        }
      },

成功的钩子
上传中的钩子
失败的钩子等等。。。

http-request方式上传

当要处理更复杂的上传场景时,饿了吗UI提供另一种上传方式,http-request方式。

<el-upload
              class="upload-demo"
              :action="uploadUrl"
              :http-request="(files) => uploadRequest(files, scope.row)"
              :accept="acceptFileTypes"
              :show-file-list="false"
              :before-upload="handleBeforeUpload">
              <el-button size="small" type="primary">上传</el-button>

            </el-upload>

这里我们给action属性随便添加一个字符串,因为该属性必传,所以不传的话会报错。
接着在插槽里获取一些额外的参数,

首先来说一下这里我为什么选择第二种方式,因为该业务场景需要我在上传完文件后根据情况在将返回的文件下载保存,而下载文件需要传入额外的参数,responseType,否则下载下来就是乱码,从而选择了这种上传方式。

uploadRequest(fileObj, row) {//自定义上传方法
        let formData = new FormData()//创建formdata实例
        formData.append('file', fileObj.file)//添加文件
        formData.append('hospitalCode', row.hospitalCode)//添加额外参数
        return axios({
          method: 'post',
          url: '/apiUser/user/batchIncrease',
          data: formData,
          responseType: 'blob'
        })
        .then(res => {//成功
        let isBackFileName = res.headers['content-disposition']//判断是否有文件返回
          if (!isBackFileName) {
            this.$message({
              type: 'success',
              message: "上传成功"
            })
          } else {//数据错误返回
            this.$message({
              type: 'warning',
              message: "当前上传的模板数据有错误,请修正后重试。"
            })
            const fileName = 'error.xls'
            saveExcelFileMethod(res, fileName)
          }
        })
      },

说一下这里的具体实现,首先初始化了一个formdata对象,formdata对象的作用如下:

1.用一些键值对来模拟一系列表单控件:即把form中所有表单元素的name与value组装成
一个queryString

  1. 异步上传二进制文件。

接着我们用append去往里面追加一些参数,
比如我们这里添加了文件,添加了一些额外的参数,然后使用axios发送请求,这里我在请求体里加了responseType属性,为的就是处理后端可能返回的文件流,

这里根据后端是否返回文件名来判断是否要下载文件,
response.headers['content-disposition']这里是固有的response的头部信息,所以我们根据这个属性来判断是否有文件返回,

saveExcelFileMethod方法是我们封装的一个工具函数,他的作用就是下载文件,有时后端会直接将文件流返回那么我们这里直接将response传入,而有时候真正需要被下载的文件流藏在了response的data里面。同时如果我们使用二次封装的axios的话,因为我们大多数场景只需要response.data里的message和statuscode,所以二次封装的axios可能有时候在响应拦截器这里会直接将response过滤掉。具体的可以看我的另一篇文章//TODO

最后修改:2021 年 12 月 10 日
如果觉得我的文章对你有用,可以对我进行您主观即不限定金额大小的打赏。