自定義element UI的upload組件

  • 2019 年 11 月 20 日
  • 筆記

簡介

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)  }