首页IT科技elupload跨域问题(使用el-upload组件实现递归多文件上传)

elupload跨域问题(使用el-upload组件实现递归多文件上传)

时间2025-05-05 04:19:55分类IT科技浏览4333
导读:一、需求描述:在页面上点击按钮弹出选择电脑文件的界面,可以一次性选择多个文件一起上传到服务器上,并把上传成功的文件展示在页面上。...

一            、需求描述:在页面上点击按钮弹出选择电脑文件的界面            ,可以一次性选择多个文件一起上传到服务器上                  ,并把上传成功的文件展示在页面上            。

·

二                  、问题阐述:el-upload是支持多文件上传的      ,但是是同步进行的      ,你点击上传按钮                  ,选择了多个文件后点击确定            ,会同时调用上传文件的接口      ,这样很容易导致服务器奔溃                  ,导致接口报错                  。

·

三      、解决方法:为了解决这一难题            ,本文采用递归的方法来实现精准上传文件      。

·

四      、实现思路:递归上传是指:你选择了n个文件点击确定后,第一个接口上传成功或者失败后                  ,再调用第二个接口上传第二个文件                  ,依次等待上传完所有文件,这样做法可以大大减轻服务器的压力            ,就是上传时间会比较长      。上传效果请看下方动态示例图

 主要逻辑详解:

1                  、首先需要先取消组件的自动上传操作                  ,把属性auto-upload的值设置为false      ,就禁用了文件的自动上传功能了            ,把自动转化为手动                  ,之所以选择多个文件会并行调用上传接口      ,就是这个属性导致的                  。

·

2            、属性auto-upload设置为false之后      ,action的属性就失效了                  ,只会触发change事件      、上传失败on-error事件以及上传个数限制before-upload事件            。

·

3                  、关键点就在于change事件            ,选择了多少个文件      ,这个事件就会执行多少次                  ,例如你选择了100个文件            ,change事件就会循环执行100次,为了保证上传的准确性                  ,这里顺手写了防抖事件                  ,通过防抖,可以清楚的知道            ,上传进度到哪了                  ,change事件什么时候结束      ,在这里就可以开始调用后端给我们的上传接口了      。

·

4.因为我是想减少服务器压力            ,既在上一个文件上传结束后                  ,再去上传下一个文件                  。故      ,我采用了递归一次传一个(递归逻辑在submitUpload2事件里)            。

同样的      ,如果你想只调用一次接口                  ,将1000个文件传给后端            ,那么你就将submitUpload2递归事件给修改调      ,改成调一次接口                  ,传所有file文件数组即可(具体看你们后端的数据结构)。

·

5.因为是上传多个文件            ,时间肯定长,如果你不想继续传递后续文件                  ,就调用submitAbort即可                  。但是element文档说的abort()取消上传事件不生效                  。所以我是直接将上传列表给置空了                  ,所以递归也就结束了就不传递了。

. 6.同样因为上传时间长,我就设置了进度条(当前已上传的个数/所有需要上传个数)            。但是你如果切换到其他页面的话            ,再切换到当前上传vue页面                  ,因为生命周期原因导致看不到上传进度                  。所以可以将这个上传vue页面使用keep-alive进行路由缓存      ,这样除了刷新浏览器外            ,切换到当前页还是会读缓存会看到上传进度      。(如果

你既想要缓存进度条                  ,又想要刷新页面的list等某些数据      ,那么你缓存此页面      ,然后在activated单独调获取list数据方法即可)            。

.
7.因为我的需要是                  ,选择文件成功后            ,默认去上传      ,所以我是在防抖事件后就去调递归上传了                  。正常情况下                  ,其实需要点击这个按钮然后去上传的            ,既手动点击上传(被注释掉了)<!-- <el-button style="margin-left: 10px;" size="small" type="success" @click="submitUpload2">手动点击上传</el-button> -->

以下代码仅供参考,可以直接复制使用(注意将axios的接口转化为后端提供的接口即可)!

<template> <div class="group_insurance_order1" style="padding-top:100px;"> <!-- :auto-upload="false" 是否在选取文件后立即进行上传 false阻止自动上传 -- 且上传前和上传成功的事件都不会再触发 只会触发@change事件了 :http-request="uploadFile" 覆盖默认的上传行为                  ,可以自定义上传的实现(this.$refs.upload1.submit() 会触发调用uploadFile函数) --> <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" style="margin-top: -10px;line-height: 20px;"> 将文件拖到此处                  ,<em v-if="!disabledUpload">或点击上传(单个文件需小于100M,一次最多上传1000个pdf文件)</em><em v-else>(文件正在上传中,请等待...)</em> </div> </el-upload> <div> <!-- <el-button style="margin-left: 10px;" size="small" type="success" @click="submitUpload2">手动点击上传</el-button> --> <el-button v-if="showPercent" style="margin-left: 10px;" size="small" type="success" @click="submitAbort">取消后续文件上传</el-button> </div> <div style="color:orange;" v-if="showPercent">上传过程请勿刷新浏览器和跳转其他页面...</div> <!-- 进度条 --> <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,//总上传个数 percentNow: 0,//当前上传个数 showDesc: ,//结束文案 showPercent: false,//显示上传进度条 time: null,// change事件是否结束 是否可以直接调手动上传事件(目前设置1.5s) disabledUpload: false,//正在上传中 禁止再次选择文件上传 fileData: { },//上传参数 fileList1: [], } }, activated: { // 对于每次进入页面想要刷新的数据            ,放在这里调用即可 例如 this.getList() }, methods: { // 超出限制个数提示 handleExceed (files, fileList) { console.log(当前限制一次性最多上传1000个文件, files, fileList) this.$message.warning("当前限制一次性最多上传1000个文件") }, changeFile (file, fileList) { this.disabledUpload = true console.log(changeFile, file, fileList) const isLt2M = file.size / 1024 / 1024 < 100 if (!isLt2M) { this.$message.warning(上传文件大小不能超过 100M) // return false // 这个return无效 故去掉 } if (!(file.name.indexOf(.pdf) > -1)) { this.$message.warning("当前仅支持pdf格式的文件上传") // return false // 这个return无效 故去掉 } // 符合条件的进入待传列表 this.upFileList = [] for (let x of fileList) { if (x.raw && (x.name.indexOf(.pdf) > -1) && (x.size / 1024 / 1024 < 100)) {// 过滤掉非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(防抖 高频触发后n秒内只会执行一次 再次触发重新计时) this.fnBegin()//说明此时change了所有文件了 可以上传了 }, 1500) }, fnBegin () { console.log(此时change了所有文件 开始上传, this.upFileList) this.submitUpload2() }, // 正式上传掉后端接口 submitUpload2 () { if (this.upFileList.length > 0) { this.showPercent = true this.fileNum = new FormData() // new formData对象 this.fileNum.append(file, this.upFileList[0]) // append增加数据 this.fileNum.append(name, this.upFileList[0].name) // append增加数据 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 => { // 每次上传当前一个后 不论成功失败就删除当前这个--如果上传失败想继续传当前这个 就把这两行注释掉 this.percentNow = this.percentNow + 1 this.upFileList.shift() console.log(上传返回, res2) if (res2.data.success) { // this.$message({ // message: "上传成功", // type: success // }) // 进行递归 上传下一个 this.submitUpload2() } else { _vm.$message({ message: res2.data.return_message || 上传失败, type: "error", }) // 进行递归 上传下一个 this.showDesc = 上传结束                  ,部分文件上传失败 this.submitUpload2() } }) .catch(error => { console.log(error) _vm.$message({ message: error || 上传失败, type: "error", }) // 每次上传当前一个后 不论成功失败就删除当前这个--如果上传失败想继续传当前这个 就把这两行注释掉 this.percentNow = this.percentNow + 1 this.upFileList.shift() // 进行递归 上传下一个 this.showDesc = 上传结束      ,部分文件上传失败 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(请先选择文件!) this.percentTotal = 0 this.percentNow = 0 } else { this.$message.success(已部分上传成功            ,且取消后续文件上传!) this.percentTotal = 0 this.percentNow = 0 } return false } }, // 终止后需上传 submitAbort () { this.showPercent = false // .abort()不生效                  ,故自己直接将this.upFileList置空 那么就不会走到递归了 就制止后续的上传了 this.upFileList = [] // this.upFileList.forEach(ele => { // this.$refs.upload1.abort(ele) // }) // this.$refs.upload1.abort() // this.$message.warning(已取消后续文件上传!) }, fileErr (err, file, fileList) { this.$message({ message: file.name + 上传失败, type: "error", }) }, // 这两个事件不会再触发--因为阻止了自动上传 beforeAvatarUpload (file) { console.log(上传文件前, file) }, msgSuccessOne (data, file, fileList) { console.log(成功, file) }, }, }; </script>

创心域SEO版权声明:以上内容作者已申请原创保护,未经允许不得转载,侵权必究!授权事宜、对本内容有异议或投诉,敬请联系网站管理员,我们将尽快回复您,谢谢合作!

展开全文READ MORE
电脑中勒索病毒可以报警吗(电脑中了勒索病毒怎么办?如何恢复?)