美文网首页vue专栏
vue+element ui+axios实现表单多文件上传

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

作者: BigFish__ | 来源:发表于2019-03-10 16:10 被阅读427次

    今天在使用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 上传

    相关文章

      网友评论

        本文标题:vue+element ui+axios实现表单多文件上传

        本文链接:https://www.haomeiwen.com/subject/epnupqtx.html