溫馨提示×

您好,登錄后才能下訂單哦!

密碼登錄×
登錄注冊(cè)×
其他方式登錄
點(diǎn)擊 登錄注冊(cè) 即表示同意《億速云用戶服務(wù)條款》

怎么使用el-upload組件實(shí)現(xiàn)遞歸多文件上傳

發(fā)布時(shí)間:2023-03-31 11:11:20 來(lái)源:億速云 閱讀:98 作者:iii 欄目:開(kāi)發(fā)技術(shù)

本篇內(nèi)容介紹了“怎么使用el-upload組件實(shí)現(xiàn)遞歸多文件上傳”的有關(guān)知識(shí),在實(shí)際案例的操作過(guò)程中,不少人都會(huì)遇到這樣的困境,接下來(lái)就讓小編帶領(lǐng)大家學(xué)習(xí)一下如何處理這些情況吧!希望大家仔細(xì)閱讀,能夠?qū)W有所成!

    一、需求描述:

    在頁(yè)面上點(diǎn)擊按鈕彈出選擇電腦文件的界面,可以一次性選擇多個(gè)文件一起上傳到服務(wù)器上,并把上傳成功的文件展示在頁(yè)面上。

    二、問(wèn)題闡述:

    el-upload是支持多文件上傳的,但是是同步進(jìn)行的,你點(diǎn)擊上傳按鈕,選擇了多個(gè)文件后點(diǎn)擊確定,會(huì)同時(shí)調(diào)用上傳文件的接口,這樣很容易導(dǎo)致服務(wù)器奔潰,導(dǎo)致接口報(bào)錯(cuò)。

    三、解決方法:

    為了解決這一難題,本文采用遞歸的方法來(lái)實(shí)現(xiàn)精準(zhǔn)上傳文件。

    四、實(shí)現(xiàn)思路:

    遞歸上傳是指:你選擇了n個(gè)文件點(diǎn)擊確定后,第一個(gè)接口上傳成功或者失敗后,再調(diào)用第二個(gè)接口上傳第二個(gè)文件,依次等待上傳完所有文件,這樣做法可以大大減輕服務(wù)器的壓力,就是上傳時(shí)間會(huì)比較長(zhǎng)。上傳效果請(qǐng)看下方動(dòng)態(tài)示例圖

    怎么使用el-upload組件實(shí)現(xiàn)遞歸多文件上傳

    主要邏輯詳解:

    1、首先需要先取消組件的自動(dòng)上傳操作,把屬性auto-upload的值設(shè)置為false,就禁用了文件的自動(dòng)上傳功能了,把自動(dòng)轉(zhuǎn)化為手動(dòng),之所以選擇多個(gè)文件會(huì)并行調(diào)用上傳接口,就是這個(gè)屬性導(dǎo)致的。

    2、屬性auto-upload設(shè)置為false之后,action的屬性就失效了,只會(huì)觸發(fā)change事件、上傳失敗on-error事件以及上傳個(gè)數(shù)限制before-upload事件。

    3、關(guān)鍵點(diǎn)就在于change事件,選擇了多少個(gè)文件,這個(gè)事件就會(huì)執(zhí)行多少次,例如你選擇了100個(gè)文件,change事件就會(huì)循環(huán)執(zhí)行100次,為了保證上傳的準(zhǔn)確性,這里順手寫(xiě)了防抖事件,通過(guò)防抖,可以清楚的知道,上傳進(jìn)度到哪了,change事件什么時(shí)候結(jié)束,在這里就可以開(kāi)始調(diào)用后端給我們的上傳接口了。

    4.因?yàn)槲沂窍霚p少服務(wù)器壓力,既在上一個(gè)文件上傳結(jié)束后,再去上傳下一個(gè)文件。故,我采用了遞歸一次傳一個(gè)(遞歸邏輯在submitUpload2事件里)。同樣的,如果你想只調(diào)用一次接口,將1000個(gè)文件傳給后端,那么你就將submitUpload2遞歸事件給修改調(diào),改成調(diào)一次接口,傳所有file文件數(shù)組即可(具體看你們后端的數(shù)據(jù)結(jié)構(gòu))。

    5.因?yàn)槭巧蟼鞫鄠€(gè)文件,時(shí)間肯定長(zhǎng),如果你不想繼續(xù)傳遞后續(xù)文件,就調(diào)用submitAbort即可。但是element文檔說(shuō)的abort()取消上傳事件不生效。所以我是直接將上傳列表給置空了,所以遞歸也就結(jié)束了就不傳遞了。

    6.同樣因?yàn)樯蟼鲿r(shí)間長(zhǎng),我就設(shè)置了進(jìn)度條(當(dāng)前已上傳的個(gè)數(shù)/所有需要上傳個(gè)數(shù))。但是你如果切換到其他頁(yè)面的話,再切換到當(dāng)前上傳vue頁(yè)面,因?yàn)樯芷谠驅(qū)е驴床坏缴蟼鬟M(jìn)度。所以可以將這個(gè)上傳vue頁(yè)面使用keep-alive進(jìn)行路由緩存,這樣除了刷新瀏覽器外,切換到當(dāng)前頁(yè)還是會(huì)讀緩存會(huì)看到上傳進(jìn)度。(如果你既想要緩存進(jìn)度條,又想要刷新頁(yè)面的list等某些數(shù)據(jù),那么你緩存此頁(yè)面,然后在activated單獨(dú)調(diào)獲取list數(shù)據(jù)方法即可)。

    7.因?yàn)槲业男枰?,選擇文件成功后,默認(rèn)去上傳,所以我是在防抖事件后就去調(diào)遞歸上傳了。正常情況下,其實(shí)需要點(diǎn)擊這個(gè)按鈕然后去上傳的,既手動(dòng)點(diǎn)擊上傳(被注釋掉了)<!-- <el-button style="margin-left: 10px;" size="small" type="success" @click="submitUpload2">手動(dòng)點(diǎn)擊上傳</el-button> -->

    以下代碼僅供參考,可以直接復(fù)制使用(注意將axios的接口轉(zhuǎn)化為后端提供的接口即可)!

    <template>
      <div class="group_insurance_order1" >
        <!--
          :auto-upload="false" 是否在選取文件后立即進(jìn)行上傳 false阻止自動(dòng)上傳 -- 且上傳前和上傳成功的事件都不會(huì)再觸發(fā) 只會(huì)觸發(fā)@change事件了
          :http-request="uploadFile"  覆蓋默認(rèn)的上傳行為,可以自定義上傳的實(shí)現(xiàn)(this.$refs.upload1.submit()  會(huì)觸發(fā)調(diào)用uploadFile函數(shù))
        -->
        <el-upload ref="upload1" class="upload-demo" action="/chc-shop/api/v1/accident/szcp/electronicfile/upload" accept=".pdf" :disabled="disabledUpload" :auto-upload="false" :on-change="changeFile" :on-error='fileErr' :on-exceed="handleExceed" :file-list="fileList1" :before-upload="beforeAvatarUpload" :on-success="msgSuccessOne" :data="fileData" list-type="picture" drag :show-file-list="false" :multiple="true" :limit="1000">
          <i class="el-icon-upload"></i>
          <div class="el-upload__text" >
            將文件拖到此處,<em v-if="!disabledUpload">或點(diǎn)擊上傳(單個(gè)文件需小于100M,一次最多上傳1000個(gè)pdf文件)</em><em v-else>(文件正在上傳中,請(qǐng)等待...)</em>
          </div>
        </el-upload>
     
        <div>
          <!-- <el-button  size="small" type="success" @click="submitUpload2">手動(dòng)點(diǎn)擊上傳</el-button> -->
          <el-button v-if="showPercent"  size="small" type="success" @click="submitAbort">取消后續(xù)文件上傳</el-button>
        </div>
     
        <div  v-if="showPercent">上傳過(guò)程請(qǐng)勿刷新瀏覽器和跳轉(zhuǎn)其他頁(yè)面...</div>
        <!-- 進(jìn)度條 -->
        <el-progress v-if="showPercent" :percentage="Number((percentNow*100/percentTotal).toFixed(0))"></el-progress>
     
      </div>
    </template>
     
    <script>
    import axios from 'axios'
    export default {
      data () {
        return {
          fileNum: '',  // 單詞遞歸上傳的文件
          upFileList: '',//需要依次上傳的待傳列表
          percentTotal: 0,//總上傳個(gè)數(shù)
          percentNow: 0,//當(dāng)前上傳個(gè)數(shù)
          showDesc: '',//結(jié)束文案
          showPercent: false,//顯示上傳進(jìn)度條
          time: null,// change事件是否結(jié)束 是否可以直接調(diào)手動(dòng)上傳事件(目前設(shè)置1.5s)
          disabledUpload: false,//正在上傳中 禁止再次選擇文件上傳
     
          fileData: {
          },//上傳參數(shù)
     
          fileList1: [],
     
        }
      },
      activated: {
        // 對(duì)于每次進(jìn)入頁(yè)面想要刷新的數(shù)據(jù),放在這里調(diào)用即可 例如 this.getList()
      },
      methods: {
        // 超出限制個(gè)數(shù)提示
        handleExceed (files, fileList) {
          console.log('當(dāng)前限制一次性最多上傳1000個(gè)文件', files, fileList)
          this.$message.warning("當(dāng)前限制一次性最多上傳1000個(gè)文件")
        },
        changeFile (file, fileList) {
          this.disabledUpload = true
     
          console.log('changeFile', file, fileList)
          const isLt2M = file.size / 1024 / 1024 < 100
          if (!isLt2M) {
            this.$message.warning('上傳文件大小不能超過(guò) 100M')
            // return false // 這個(gè)return無(wú)效 故去掉
          }
     
          if (!(file.name.indexOf('.pdf') > -1)) {
            this.$message.warning("當(dāng)前僅支持pdf格式的文件上傳")
            // return false // 這個(gè)return無(wú)效 故去掉
          }
     
     
          // 符合條件的進(jìn)入待傳列表
          this.upFileList = []
          for (let x of fileList) {
            if (x.raw && (x.name.indexOf('.pdf') > -1) && (x.size / 1024 / 1024 < 100)) {// 過(guò)濾掉非pdf 和小于100M的
              this.upFileList.push(x.raw)
              this.percentTotal = this.upFileList.length
              this.percentNow = 0
              this.showPercent = false
              this.showDesc = ''
            }
          }
     
          clearTimeout(this.time)
          this.time = setTimeout(() => {
            this.time = null
            console.log('防抖 高頻觸發(fā)后n秒內(nèi)只會(huì)執(zhí)行一次  再次觸發(fā)重新計(jì)時(shí)')
            this.fnBegin()//說(shuō)明此時(shí)change了所有文件了 可以上傳了
          }, 1500)
     
        },
        fnBegin () {
          console.log('此時(shí)change了所有文件 開(kāi)始上傳', this.upFileList)
          this.submitUpload2()
        },
        // 正式上傳掉后端接口
        submitUpload2 () {
          if (this.upFileList.length > 0) {
            this.showPercent = true
     
            this.fileNum = new FormData()  // new formData對(duì)象
            this.fileNum.append('file', this.upFileList[0])  // append增加數(shù)據(jù)
            this.fileNum.append('name', this.upFileList[0].name)  // append增加數(shù)據(jù)
     
            let _vm = this
            axios({
              url: '/chc-shop/api/v1/accident/szcp/electronicfile/upload',
              headers: {
                "Content-Type": "multipart/form-data",
              },
              method: "post",
              data: this.fileNum,
            })
              .then(res2 => {
                // 每次上傳當(dāng)前一個(gè)后 不論成功失敗就刪除當(dāng)前這個(gè)--如果上傳失敗想繼續(xù)傳當(dāng)前這個(gè) 就把這兩行注釋掉
                this.percentNow = this.percentNow + 1
                this.upFileList.shift()
     
     
                console.log('上傳返回', res2)
                if (res2.data.success) {
                  // this.$message({
                  //   message: "上傳成功",
                  //   type: 'success'
                  // })
     
                  // 進(jìn)行遞歸 上傳下一個(gè)
                  this.submitUpload2()
     
                } else {
                  _vm.$message({
                    message: res2.data.return_message || '上傳失敗',
                    type: "error",
                  })
     
                  // 進(jìn)行遞歸 上傳下一個(gè)
                  this.showDesc = '上傳結(jié)束,部分文件上傳失敗'
                  this.submitUpload2()
                }
              })
              .catch(error => {
                console.log(error)
                _vm.$message({
                  message: error || '上傳失敗',
                  type: "error",
                })
     
                // 每次上傳當(dāng)前一個(gè)后 不論成功失敗就刪除當(dāng)前這個(gè)--如果上傳失敗想繼續(xù)傳當(dāng)前這個(gè) 就把這兩行注釋掉
                this.percentNow = this.percentNow + 1
                this.upFileList.shift()
     
                // 進(jìn)行遞歸 上傳下一個(gè)
                this.showDesc = '上傳結(jié)束,部分文件上傳失敗'
                this.submitUpload2()
              })
     
          } else {
            this.disabledUpload = false
            this.showPercent = false
            this.upFileList = [] //清空待傳列表
     
            this.$refs.upload1.clearFiles()
            this.fileList1 = []
     
            if ((this.percentNow == this.percentTotal) && this.percentTotal) {
              this.$message.success(this.showDesc ? this.showDesc : '已全部上傳成功!')
              this.percentTotal = 0
              this.percentNow = 0
              this.showDesc = ''
     
            } else if ((this.percentNow == this.percentTotal) && this.percentTotal == 0) {
              this.$message.warning('請(qǐng)先選擇文件!')
              this.percentTotal = 0
              this.percentNow = 0
            } else {
              this.$message.success('已部分上傳成功,且取消后續(xù)文件上傳!')
              this.percentTotal = 0
              this.percentNow = 0
     
            }
     
            return false
          }
     
        },
        // 終止后需上傳
        submitAbort () {
          this.showPercent = false
          // .abort()不生效,故自己直接將this.upFileList置空 那么就不會(huì)走到遞歸了 就制止后續(xù)的上傳了
          this.upFileList = []
     
     
          // this.upFileList.forEach(ele => {
          //   this.$refs.upload1.abort(ele)
          // })
          // this.$refs.upload1.abort()
          // this.$message.warning('已取消后續(xù)文件上傳!')
        },
        fileErr (err, file, fileList) {
          this.$message({
            message: file.name + '上傳失敗',
            type: "error",
          })
        },
     
     
     
    	// 這兩個(gè)事件不會(huì)再觸發(fā)--因?yàn)樽柚沽俗詣?dòng)上傳
        beforeAvatarUpload (file) {
          console.log('上傳文件前', file)
        },
        msgSuccessOne (data, file, fileList) {
          console.log('成功', file)
        },
     
     
      },
    };
    </script>

    “怎么使用el-upload組件實(shí)現(xiàn)遞歸多文件上傳”的內(nèi)容就介紹到這里了,感謝大家的閱讀。如果想了解更多行業(yè)相關(guān)的知識(shí)可以關(guān)注億速云網(wǎng)站,小編將為大家輸出更多高質(zhì)量的實(shí)用文章!

    向AI問(wèn)一下細(xì)節(jié)

    免責(zé)聲明:本站發(fā)布的內(nèi)容(圖片、視頻和文字)以原創(chuàng)、轉(zhuǎn)載和分享為主,文章觀點(diǎn)不代表本網(wǎng)站立場(chǎng),如果涉及侵權(quán)請(qǐng)聯(lián)系站長(zhǎng)郵箱:is@yisu.com進(jìn)行舉報(bào),并提供相關(guān)證據(jù),一經(jīng)查實(shí),將立刻刪除涉嫌侵權(quán)內(nèi)容。

    AI