element-ui上傳組件多個文件同時上傳請求一次後臺接口(前後端代碼版)

記錄時間

          2020年10月27日 22點38分

前言

         在使用element-ui上傳組件上傳多個文件時,出現多個文件對應着多個請求,比如你要上傳3個文件,那麼將請求3個後臺接口,這樣會無形之中增加了後臺系統的服務器壓力,因此只能前端代碼做修改,使得多個文件上傳只請求1次後臺接口。而搜索了相關文章,大部分都是講解了前端的代碼,而沒有添上後臺的代碼,因此本作者藉此將我完善的前後端代碼添出來供大家參考。

前端代碼

<template>
  <div>
    <el-upload
      class="upload-demo"
      drag
      ref="upload"
      :action="uploadAction"
      :auto-upload="autoUpload"
      :on-remove="handleRemove"
      :before-remove="beforeRemove"
      :on-change="beforeUpload"
      :on-success="handleUploadSuccess"
      :on-error="handleUploadError"
      :data="extraParam"
      :headers="headers"
      :limit="fileSizeLimit"
      :file-list="fileList"
      :on-exceed="handleExceed"
      :accept="fileType"
      multiple>
      <i class="el-icon-upload"></i>
      <div class="el-upload__text">將文件拖到此處,或<em>點擊上傳</em></div>
      <div class="el-upload__tip" slot="tip">
        <span style="color: #FE6D68;">*</span>
        {{promptMessage}}
      </div>
    </el-upload>
  </div>
</template>

<script>
  import {upload} from '@/utils/upload'
  import {getToken} from '@/utils/tokenOperation'
  export default{
    name: 'FileUpload',
    props: {
      /* 上傳框提示 */
      promptMessage: {
        default: '只能上傳xls/xlsx文件',
        type: String
      },
      /* 文件上傳路徑 */
      uploadAction: {
        default: '',
        type: String
      },
      /* 文件類型 */
      fileType: {
        default: '.xlsx,.xls',
        type: String
      },
      /* 限制最大文件上傳數 */
      fileSizeLimit: {
        default: 2,
        type: Number
      }
    },
    data() {
      return {
        /* 上傳時附帶的額外參數,返回是一個對象 */
        extraParam: {},
        /* 已上傳的文件列表 */
        fileList: [],
        /* 請求頭 */
        headers: {
          'strainpreservation': getToken()
        },
        /* 是否在選取文件後立即進行上傳 */
        autoUpload: false,
      }
    },
    methods:{
      /* 文件列表移除文件成功時的鉤子 */
      handleRemove(file, fileList) {
        return this.successNotify(`已成功移除"${file.name}"文件`)
      },
      /* 處理上傳失敗時的勾子 */
      handleUploadError(err, file, fileList) {
        this.errorNotify(`文件上傳失敗`)
      },
      /* 文件刪除前的勾子 */
      beforeRemove(file, fileList) {
        return this.$confirm(`確定移除"${file.name}"文件嗎?`)
      },
      /* 上傳文件之前的鉤子 因設置了auto-upload爲false,如果使用before-upload,雖有提示,但是還是會請求服務器*/
      beforeUpload(file,fileList) {
        // 1、判斷文件名是否重複,不允許上傳相同文件
        let existFile = fileList.slice(0, fileList.length - 1).find(f => f.name === file.name)
        if(existFile){
          fileList.pop()
          this.warningNotify(file.name+" 文件已存在!")
        }
        // 2、獲取文件後綴
        fileList.forEach(everyFile => {
          const fileType = everyFile.name.substring(everyFile.name.lastIndexOf('.'))
          if(this.fileType.search(fileType) === -1){
             fileList.pop()
             this.warningNotify("上傳文件的類型不正確"+"文件類型必須爲" + this.fileType + '')
          }
        })
        this.fileList = fileList;
      },
      /* 文件超出個數限制時的鉤子 */
      handleExceed(files, fileList) {
        this.warningNotify(`當前限制選擇`+ this.fileSizeLimit +`個文件,本次選擇了 ${files.length} 個文件,已超出了文件最大上傳個數`)
      },
      /* 文件上傳成功時的鉤子 */
      handleUploadSuccess(res, file, fileList) {
        console.info(JSON.stringify(res))
      },
      /* 確定上傳 */
      submitUpload() {
        upload(this.uploadAction,this.fileList).then(res => {
          this.fileList = []
        });
      }
    }
  }
</script>

<style rel="stylesheet/scss" lang="scss" scoped>
  .el-upload__tip{
    font-weight: bold;
    font-size: 14px;
  }
  .upload_div{
    padding: 10px 0px 20px 20px;
    text-align: right;
    box-sizing: border-box;
  }
</style>
import axios from 'axios'
import { getToken } from '@/utils/tokenOperation'

export function upload(api, file) {
  var data = new FormData()
  file.forEach(everyFile => {
    data.append("file",everyFile.raw)
  })
  const config = {
    headers: {
      'strainpreservation': getToken()
       }
  }
  return axios.post(api, data, config)
}


1、getToken是自己封裝的從cookie中獲取token的方法
2、everyFile.raw就是File數據,大夥可以debug看看,或者使用console.info(everyFile)看看裏面的內容

結合前端的代碼做一些講解:

1、upload上傳組件的action屬性一定要寫

     這是upload組件約定的,無論是否使用upload內部實現的上傳方式,這個action屬性是一定要寫的,要不然會報"沒有action屬性"的錯誤。

2、action-upload設置爲false,file-list屬性也一定要寫

    action-upload設置爲false,是因爲不讓它自動上傳,因爲我們的頁面,很多時候都是當選擇完文件後,點擊按鈕才允許上傳的,而file-list屬性是存儲上傳的文件的信息。

3、當action-upload屬性設置爲false時,before-upload方法是失效的

    當action-upload屬性設置爲false時,before-upload如果做文件大小、文件類型、文件重複等邏輯的判斷,假如文件類型錯誤,return false或者Promise. reject ()方法想終止上傳時,是終止不了的,還是會請求到服務器。因此需要使用on-onchange屬性來替換

後臺代碼

  /**
    * 導入培養基信息
    * @param file
    * @return
    */
    @ApiOperation(value = "導入培養基信息",notes = "點擊頁面上的導入按鈕時請求的接口")
    @PostMapping(value = "/importMediumInfo")
    @PreAuthorize("@el.check('sys:medium:import')")
    public BaseResultVO importMediumInfo(@RequestParam("file") MultipartFile[] file){
      return iMediumInfoService.mediumFileUpload(file);
    }

* 1、後臺我使用MultipartFile數組來接收前端FormData傳來的數據。業務層的邏輯我就不添出來了,因爲後臺我是使用的EasyExcel來實現的。

   

用心對待,相信美好東西會如期歸來。ღ( ´・ᴗ・` )比

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章