网站首页 文章专栏 自定义element UI的upload组件
自定义element UI的upload组件
创建于:2019-06-25 06:17:32 更新于:2021-07-28 18:48:00 羽瀚尘 1027
vue vue,前端

简介

ElementUI中的upload组件使用固然很简便,但是我们可能有更复杂的应用。

比如要开发一个手写数字识别的前端,上传到的服务器的是一张手写数字的图片,返回识别的结果,这个应用无法直接由upload组件实现。

当然,我们也可以先上传,维护一个图片的token,然后后台根据这个token去取相应的数据。但这样不仅要维护一个token,还要和文件系统(磁盘)交互,要考虑上传到哪里、如何删除等问题。不如直接传递方便。

实现

自定义上传函数

绑定http-request到自定义函数即可

      <el-upload
        class="upload-demo"
        :http-request="uploadSectionFile"
        ref="upload"
        action=""
        :on-preview="handlePreview"
        :on-remove="handleRemove"
        :before-remove="beforeRemove"
        :limit="1"
        :on-exceed="handleExceed"
        :auto-upload="false"
        :file-list="fileList">
        <el-button   type="primary" icon="el-icon-upload">点击上传</el-button>
        <div slot="tip" class="el-upload__tip">只能上传wav文件,且不超过500kb</div>
      </el-upload>

该函数只有一个参数param, 并且param.file就是我们要上传的文件对象。

function uploadSectionFile(param){
    var fileObj = param.file
    var form = new FormData()
    form.append("file", fileObj)
    // other code ....
}

实现上传进度条

上传用axios实现,进度条由axios和uploadSectionFile的param参数配合实现。

param.file.percentparam.onProjress用来显示进度条。

let config = {
      onUploadProgress: progressEvent => {
          var complete = (progressEvent.loaded / progressEvent.total * 100 | 0)
          param.file.percent = complete
          param.onProgress(param.file)
      },
      headers: {
          'Content-Type': 'multipart/form-data'
        } 
      }

实现上传成功状态

依旧是param参数。

param.onSuccess('文件上传成功')

完整代码

vue

<template>
  <div class="home">
    <h1>Hello</h1>
    <el-row>
      <el-col :span="8">
      <el-upload
        class="upload-demo"
        :http-request="uploadSectionFile"
        ref="upload"
        action=""
        :on-preview="handlePreview"
        :on-remove="handleRemove"
        :before-remove="beforeRemove"
        :limit="1"
        :on-exceed="handleExceed"
        :auto-upload="false"
        :file-list="fileList">
        <el-button   type="primary" icon="el-icon-upload">点击上传</el-button>
        <div slot="tip" class="el-upload__tip">只能上传wav文件,且不超过500kb</div>
      </el-upload>
      </el-col>

      <el-col :span="8">
        <el-button type="primary" @click="handleButton('upload-model')" icon="el-icon-upload">加载模型</el-button>
      </el-col>
      <el-col :span="8">
        <el-button type="primary" @click="handleButton('begin-analyse')" icon="el-icon-video-play">开始分析</el-button>
      </el-col>
    </el-row>

    <el-row>
    <el-col :span="12">
      <div class="row-softmax">
        <h2>模型原始输出</h2>
          <el-table
            :data="softmax_output"
            :max-height = "330"
            border
            style="width: 100%">
            <el-table-column
              prop="label"
              label="标签"
              width="148">
            </el-table-column>
            <el-table-column
              prop="probability"
              label="概率"
              width="148">
            </el-table-column>
          </el-table>
      </div>
    </el-col>

    <el-col :span="12">
      <el-row>
        <el-col :span="24">
          <div class="time-frequency">
          <img class="base64Img" :src="time_frequency_pic_base64">
          </div>
        </el-col>
      </el-row>

      <el-row>
        <el-col :span="24">
          <div class="final-result">
          <h2>归类</h2>
          <p>  final_result }} </p>
          </div>
        </el-col>
      </el-row>

      <el-row>
        <el-col :span="24">
          <div class="save-result">
          <el-button type="primary"><i class="el-icon-upload el-icon--right"></i>保存结果</el-button>
          </div>
        </el-col>
      </el-row>
    </el-col>
    </el-row>
  </div>
</template>

<script>
import { predict } from '@/api/tensorflow'
export default {
  name: 'HelloWorld',
  data () {
    return {
      fileList: [],
      fileObj: '',
      time_frequency_pic_base64:'',
      readable_labels: [],
      final_result: '',
      softmax_output: [
        {
          'label' : '类别1',
          'probability' : 0.1
        },
        {
          'label' : '类别1',
          'probability' : 0.1
        },
        {
          'label' : '类别1',
          'probability' : 0.1
        },
        {
          'label' : '类别1',
          'probability' : 0.1
        },
        {
          'label' : '类别1',
          'probability' : 0.1
        }
      ]
    }
  },
  methods: {
    handleRemove(file, fileList) {
      console.log(file, fileList);
    },
    handlePreview(file) {
      console.log(file);
    },
    handleExceed(files, fileList) {
      this.$message.warning(`当前限制选择 1 个文件,本次选择了 ${files.length} 个文件,共选择了 ${files.length + fileList.length} 个文件`);
    },
    beforeRemove(file, fileList) {
      return this.$confirm(`确定移除 ${ file.name }?`);
    },
    uploadSectionFile(param){
      console.log(param)
    let config = {
      onUploadProgress: progressEvent => {
          var complete = (progressEvent.loaded / progressEvent.total * 100 | 0)
          param.file.percent = complete
          param.onProgress(param.file)
      },
      headers: {
          'Content-Type': 'multipart/form-data'
        } 
      }
      var fileObj = param.file
      var form = new FormData()
      form.append("file", fileObj)
      predict(form, config)
      .then( (data) => {
        console.log(data)
        this.time_frequency_pic_base64 = 'data:image/jpg;base64,' + data.data.time_frequency_pic_base64
        this.final_result = data.data.final_result
        this.softmax_output = data.data.softmax_output
        param.onSuccess('文件上传成功')
      })
    },
    handleButton(type){
       if(type == 'upload-model'){
         console.log('Not implement yet. Upload model')
       }
       else if(type == 'begin-analyse'){
         console.log('Begin anaylyse')
         this.$refs.upload.submit()
       }
    },
    handleChange(type){
      if(type == 'file'){
        this.fileObj = document.getElementById("upfile").files[0] 
      }else if(type == 'model'){

      }
    }
  }
}
</script>

axios

import axios from 'axios'
export function predict(data, config) {
  return axios.post('your_address',data,config)
}