一文搞懂element-ui的文件上传

  • 文件上传逻辑
    携带token上传文件到文件服务器,上传胜利服务器返回体里蕴含fileIdfileName,上传失败返回失败code,
  • 文件下载逻辑
    依据fileId调接口获取二进制流文件,依据fileName的后缀获取文件类型,把二进制文件依据文件类型生成文件。
  • 其余逻辑

    1. 文件上传前需判断上传文件类型(文件后缀)及文件大小是否超限,简略不做阐明

碰到问题如下

问题 1.文件上传须要携带 token,并搁置于 header 里

解决方案;
应用el-upload提供的header即可

<el-upload :headers="headers" />
data(){  return {    headers:{token:"111"}  }}

问题 2.图片预览时如果图片不存在可能会返回二进制的 json 文件流,须要非凡解决

判断预览时返回的二进制流,分状况解决

    handlePreview(file) {      // console.log('要预览的文件是:', file)      // 获取服务端返回的文件id和文件名      const fileId = file.response.body.fileId      const fileName = file.response.body.fileName      axios.post(          this.DOWNLOAD_URL,          {            body: { fileId: fileId }          },          {            // 设置axios的headers和返回数据类型            headers: this.headers,            responseType: 'blob'          }        )        .then(res => {          // 如果文件未找到还是可能会返回二进制格局的json信息,须要进行解决          // 失常状况下会返回须要的二进制文件          if (this.handleMessage(res)) {            // 解决失常状况的二进制文件            var fileType = this.getFileType(fileName)            if (fileType === 'image') {              this.downImage(res.data, fileName)            } else {              console.info('非图片格式暂无奈预览')            }          }        })    },    handleMessage(res) {      // 未解决过的response对象,如果为失常的二进制流文件返回true,如果为二进制的json文件则返回false并展现json内容      if (res.data && res.data.type) {        if (res.data.type === 'application/octet-stream') {          // 失常的二进制流文件          return true        } else if (res.data.type === 'application/json') {          // 异样的二进制的JSON文件          const reader = new FileReader()          reader.readAsText(res.data, 'utf-8')          reader.onload = e => {            const result = JSON.parse(reader.result)            const message = '下载资源文件失败' + reader.result            console.error('下载资源文件失败:', result)            this.$message({              message: message,              type: 'error',              duration: 5 * 1000            })          }          return false        }      } else {        console.error(          '函数入参response对象应该是一个残缺的对象,应该蕴含data.type属性'        )      }    },    getFileType(fileName) {      // 更多文件类型 参考 https://www.cnblogs.com/zhongcj/archive/2008/11/03/1325293.html      const arr = fileName.split('.')      const len = arr.length      let str = ''      if (len > 1) {        const allowedImageType = this.allowedImageType ||['jpg','jpeg','png']        const allowedVideoType = this.allowedVideoType || ['mp4']        const fileType = arr[arr.length - 1].toLocaleLowerCase()        if (allowedImageType.includes(fileType)) {          str = 'image'        } else if (allowedVideoType.includes(fileType)) {          str = 'video'        }      }      return str    },    downImage(blobData, fileName) {      const blob = new Blob([blobData], { type: 'image/jpeg' })      const reader = new FileReader()      reader.readAsDataURL(blob)      reader.onload = e => {        const url = URL.createObjectURL(blob)        // 取到url,间接在页面展现即可      }    },

问题 3.el-upload 组件展现为上传胜利实际上传失败问题

问题产生起因:
element-uiupload组件是依据httpCode来判断的,如果为httpCode<200||httpCode>=300则判断为上传失败,其余状况则标记为上传胜利。

而开发过程却是不解决httpCode而是依据responseBody里的code字段进行判断,尽管我也感觉通过httpCode更适合,然而碰到很多状况都是通过响应体里的code来判断的(难不成是因为后端共事不晓得怎么解决httpCode?)

handleSuccess(res, file, fileList) {  // 上传胜利函数的res是responseBody的body体  // 解决element-ui认为上传胜利(他是通过httpCode为200断定为胜利的),实际上传失败状况(通过responseBody判断)  if (res.code && res.code !== 0) {    // 上传不胜利给出提示信息    this.$message({      message: res.message || 'error',      type: 'error',      duration: 5 * 1000    })    this.$nextTick(function() {      // 移除上传失败的文件,code为0即为胜利      const successFileList = fileList.filter(ele => {        return ele.response.code + '' === '0'      })      // 从新设置列表为正确的列表      // this.fileList = successFileList      // 假上传胜利时也须要进行一次解决      this.$emit('my-update', successFileList)    })  }},

问题 4.如何在包装 el-upload 的自定义组件里获取到最新的已上传的文件列表

应用自定义的v-model解决在组件最外层获取已上传的文件列表

// 自定义组件内,设置v-modelexport default {  model: {    prop: 'fileList',    event: 'my-update',  },  props: {    // element-ui上传组件的文件列表数组    fileList: {      type: Array,      default() {        return []      },    },  },  methods: {    // 监听ele-upload的change事件 依据文档仅增加文件、上传胜利和上传失败时都会被调用    handleChange(file, fileList) {      // console.log('文件发生变化', file, fileList)      this.$emit('my-update', fileList)    },    // 删除文件后须要同步触发下事件    handleRemove(file, fileList) {      const fileId = file.response.body.fileId      // console.log('执行删除事件,要删除的文件id', fileId, fileList)      const selectedFileList = fileList.filter(ele => {        return fileId !== ele.response.body.fileId      })      // console.log('删除后文件列表:', selectedFileList)      this.$emit('my-update', selectedFileList)    },    // 同时假上传胜利时也须要进行一次解决  },}
  <!-- 父组件里应用 -->  <upload-box  v-model="uploadFileList" />