背景介绍
- 需求背景
- 后端需要批量对上传的文件进行处理
- 原生的 el-upload 批量上传会多次调用上传接口,不支持一次调用
- 前端需要对选择的文件进行批量校验
2、使用
el-upload
是因为:
- 项目是基于饿了吗组件库开发的,不想再引入其他的组件进行开发;
- 原生的
input
实现上传样式处理也比较费劲。
在网上看了大家的实现方案,发现要不然就是使用 input 进行批量上传;使用
el-upload
的场景都需要两个按钮【选择文件、上传】才能实现上面的诉求,考虑到这样的交互都不太友好,所以使用自己的方式实现。
一、实现效果
- 先来说说实现的效果,点击上传按钮,弹出文件选择,选择后直接调用上传接口进行上传,只调用一个接口。
- 项目效果
功能效果
请求
template
代码
request
代码
二、具体说明
0.
data变量说明
data(){return{uploadCfg:{fileList:[],// 默认绑定的文件列表validFileList:[]// 通过校验的文件列表}};}
下面来解释下以上
template
中重要的两个组件属性
1.
handleBeforeUpload
上传文件之前的校验:至少要包含一个
excel
文件;如果校验通过,请求接口;如果校验不通过,终止接口的请求,并给出校验不通过的提示。
/**
* @desc 上传之前进行文件校验
* @param file 当前文件
*/handleBeforeUpload(file){let vm =this;returnnewPromise((resolve, reject)=>{// 收集文件列表this.uploadCfg.validFileList.push(file);// 校验文件列表
vm.handleDebounceVarifyFile();setTimeout(function(){if(!_.isEmpty(vm.uploadCfg.validFileList)){resolve(true);}else{reject(true);}},100);});}
可以看到这里返回了
Promise
,看下官方给的解释,如下图,就是说支持用
Promise
的方式返回结果,没有直接返回
false
的原因下面说明一下。
el-upload
的handleBeforeUpload
会在批量上传的时候触发多次,即选择几个文件就会调用几次,我们的需求是,至少要包含一个excel
文件,这种情况下需要收集所有选中的文件进行批量校验,单个的触发是不能满足的,所以这里使用了一个【防抖函数】handleDebounceVarifyFile
通过短时间内最后一次触发,来达到批量校验文件的效果。 因为会多次触发,所以这里的校验函数,返回的是一个Promise
。
下面是防抖函数的逻辑说明,具体可以根据自己的应用场景去开发这里的逻辑
/**
* @desc 防抖触发文件上传前,保证批量校验
*/handleDebounceVarifyFile: _.debounce(function(){let excel_file ={};if(_.isEmpty(this.uploadCfg.validFileList)){return;}
excel_file =this.uploadCfg.validFileList.find(item=>{return/\.(xls)|\.(xlsx)$/.test(item.name);});// 如果文件校验不合理,清空合法文件列表,并提示if(_.isEmpty(excel_file)){this.uploadCfg.validFileList =[];this.$message.warning('至少上传一个xls或者xlsx格式的文件!');}},20)
2.
handleUploadHttp
这里使用自定义的上传方法,和上传前校验一样,
el-ipload
默认会多次调用上传接口,我们需要做的也是使用防抖的思路,控制最后一次触发上传回调的时候去构造批量的文件数据,请求接口,下面是具体代码:
/**
* @desc 自定义上传
*/handleUploadHttp(){this.handleDebounceUpload();}/**
* @desc 防抖触发文件上传前,保证批量上传
*/handleDebounceUpload: _.debounce(function(){if(_.isEmpty(this.uploadCfg.validFileList)){return;}let formData =newFormData();this.uploadCfg.validFileList.forEach((item_file)=>{
formData.append(`files`,item_file);});
batchUploadApi.uploadXsxx(formData).then(()=>{this.$message.success('附件已上传成功,请等待数据入库!');this.uploadCfg.validFileList =[];}).catch(err=>{
console.log('批量上传附件失败', err);});},20)
三、结语
至此,个人认为比较完美的解决了问题,分享出来希望可以帮助到有同样问题的人~
版权归原作者 DoubleNa 所有, 如有侵权,请联系我们删除。