vue专栏

vue+element ui+axios实现表单多文件上传

2019-03-10  本文已影响427人  BigFish__

今天在使用vue-element-admin框架撸后台的过程中遇到了单表单中上传多文件的问题。在此做下记录。

后端有一个模型上传的接口,前端需要通过post方法将模型文件、模型封面以及其他额外信息提交给后端,其中模型的文件和封面是文件类型,其他信息是string类型。

由于element的upload组件是单文件post上传的形式,没法使用它的el-upload组件在一个表单中提交多个文件给后端。

这里选择使用默认的表单提交功能来实现,html代码如下:

      <el-form ref="dataForm" :rules="rules" :model="temp" label-position="left" label-width="80px" style="width: 400px; margin-left:50px;">
        <el-form-item label="模型名字" prop="name" >
          <el-input v-model="temp.name"/>
        </el-form-item>
        <el-form-item label="模型描述" prop="description">
          <el-input v-model="temp.description"/>
        </el-form-item>
        <el-form-item label="模型封面" prop="cover">
          <el-input v-model="temp.cover" type="file" @change="handleFileChange($event, 'cover')" />
        </el-form-item>
        <el-form-item label="模型" prop="model">
          <el-input v-model="temp.model" type="file" @change="handleFileChange($event, 'model')" />
        </el-form-item>
      </el-form>

然后添加handleFileChange方法:

    handleFileChange (event, type) {
      this.temp[type] = event.target.files[0]
    }

这个方法的本意是是拿到event对象之后,将event对象中的文件赋值给待提交的表单对象temp,但是传进来的event参数不是一个对象,而是一个路径形式的字符串:

event对象
这里是el-input这个组件的原因导致的,有两种解决办法,一种是给这两个el-input各加一个id属性,然后在handleFileChange方法中通过getElementById来获取对象的files属性。不过这种方法在代码上相对就显得有些臃肿。于是我选择使用原生的input标签来接受event对象,修改过之后的html代码如下:
        <el-form-item label="模型封面" prop="cover">
          <input type="file" @change="handleFileChange($event, 'cover')">
        </el-form-item>
        <el-form-item label="模型" prop="model">
          <input type="file" @change="handleFileChange($event, 'model')" >
        </el-form-item>

接下来实现createModel方法:

    createModel () {
      this.$refs['dataForm'].validate((valid) => {
        if (valid) {
          uploadModel(this.temp)
            .then(() => {
              this.dialogFormVisible = false
              this.$notify({
                title: '成功',
                message: '上传成功',
                type: 'success',
                duration: 2000
              })
              this.getList()
              this.resetTemp()
            })
        }
      })
    },

上面代码中的uploadModel方法是经过封装之后的axios请求,源码如下:

const uploadModel = function (formData) {
  return request({
    url: '/api/model',
    method: 'post',
    headers: {
      'Content-Type': 'multipart/form-data'
    },
    data: formData,
    transformRequest: [function (data, headers) {
      const formData = new FormData()
      for (const key of Object.keys(data)) {
        formData.append(key, data[key])
      }
      return formData
    }]
  })
}

这里首先需要注意的是将Content-Type请求头的值改为multipart/form-data,表示表单形式是文件上传。其次要注意post的数据需要是FormData类型,不能是普通的对象,这里通过transformRequest方法,将参数formData中的属性复制到新建的FormData对象上。

参考资料:
vue-element-admin
Element - Upload 上传

上一篇下一篇

猜你喜欢

热点阅读