antd 批量上传文件逻辑

  • antd 批量上传文件逻辑已关闭评论
  • 123 次浏览
  • A+
所属分类:Web前端
摘要

  通过 antd 框架的 Upload 控件,采用手动上传的方式,先选择需要上传的文件(控制文件数量以及大小),再根据所选的文件列表,循环上传,期间通过 Spin 控件提示上传中。


基本步骤

  通过 antd 框架的 Upload 控件,采用手动上传的方式,先选择需要上传的文件(控制文件数量以及大小),再根据所选的文件列表,循环上传,期间通过 Spin 控件提示上传中。

效果展示

  antd 批量上传文件逻辑

 控件引用

  Upload 控件配置:

 1 props : {  2   multiple: true,  3   maxCount:20,//限制最多显示 20 个文件  4   onRemove: (file) => {//删除列表文件  5     let fileListbatch_curr=this.state.fileListbatch;  6     console.log("props-onRemove-fileListbatch_curr:",fileListbatch_curr);  7     let index = fileListbatch_curr.findIndex(item=>item.uid==file.uid);  8     console.log("props-onRemove-obj:",index,file.uid);  9     if(index==-1){ 10       //message.warning("未删除成功!") 11       return; 12     }else{ 13       const newFileList = fileListbatch_curr.slice(); 14       newFileList.splice(index, 1); 15       console.log("props-onRemove-newFileList:",newFileList); 16       this.setState({fileListbatch:newFileList}); 17       let uploadsuccesslist_curr=this.state.uploadsuccesslist; 18       let indexsuccess=uploadsuccesslist_curr.findIndex(item=>item.uid==file.uid);//根据唯一码 uid 查找目标文件的索引 19       if(indexsuccess!=-1){ 20         uploadsuccesslist_curr.splice(indexsuccess, 1);//删除 21         console.log("props-onRemove-uploadsuccesslist_curr:",uploadsuccesslist_curr); 22         this.setState({uploadsuccesslist:uploadsuccesslist_curr}); 23       } 24     } 25   }, 26   beforeUpload: (file) => {//添加文件,将文件加入临时列表,准备上传 27     let fileListbatch_curr=this.state.fileListbatch; 28     let ff=fileListbatch_curr.find((item)=>item.name==file.name); 29     if(ff==undefined){ 30       fileListbatch_curr.push(file); 31       this.setState({fileListbatch:fileListbatch_curr,uploadflag:false}); 32       return false; 33     } 34     else{ 35       message.warning("存在同名文件已选择,请确认!"); 36       return Upload.LIST_IGNORE;//列表中不显示 37     } 38   }, 39   fileListbatch_cc, 40 }

  界面元素排列:

 1 <Upload {...props}>  2   <Button icon={<UploadOutlined />}>选择文件(Max:20Pcs, Max:200MB)</Button>  3 </Upload>  4 <Button  5   type="primary"  6   onClick={this.batchUploadReports}  7   disabled={fileListbatch.length === 0}  8   //loading={uploading}  9   style={{ marginTop: 20,width:180 }} 10 > 11   {/* {uploading ? 'Uploading' : 'Start Upload'} */} 12   开始上传 13 </Button> 14 <label style={{ lineHeight: "0px", color: '#bfbfbf', fontSize: 10,float:'left',marginBottom:20 }}>支持扩展名:apk/exe/pdf/xls/doc/ppt等</label>

处理逻辑

  根据文件列表,循环上传全部文件。

  【后端采用 .Net 5.0 WebAPI 详见:大文件分片上传 中的“后端部分”】

  1 //批量上传文件   2 batchUploadReports = () => {   3 this.setState({uploadsuccesslist:[]})   4 let uploadsuccesslist_curr=[];   5 this.formRef_upload.current.validateFields()   6 .then(formrefcurr => {   7   if(formrefcurr["baogaolb"]==0||formrefcurr["baogaolx"].length==0){   8     message.warning("请检查必填项!");   9     return null;  10   }  11   this.setState({fileuploading:true,uploadsuccesslist:[],tipContent:"报告文件上传中,请耐心等待..."});  12   let fileListbatch_curr2=this.state.fileListbatch;  13   let filecount=fileListbatch_curr2.length;  14   let filecount_success=0;  15   if(filecount>20){//只取前 20 个文件  16     filecount=20;  17     fileListbatch_curr2=fileListbatch_curr2.splice(0,20);  18   }  19   try{//通过抛出异常,来中断 foreach  20     fileListbatch_curr2.forEach(element => {//文件 list 循环上传  21       if(element.size/(1024*1024)>200){  22         this.setState({fileuploading:false,uploadsuccesslist:[],tipContent:"报告文件上传中,请耐心等待..."})  23         message.warning("单个报告大小不允许超过 200MB,请检查后继续上传!");  24         // fileListbatch_curr2.length=0;  25         throw new Error(element)//若有不符合条件的文件,抛出异常中断循环  26       }  27       else{  28         let filename=element.name;  29         let chunklistcurr=this.createFileChunk(element).map(({ file, name }, index) => {//createFileChunk:创建文件切片,可处理大文件  30             return {  31               chunk: file,  32               size: file.size,  33               percent: 0,  34               //filename:file.  35               name: name,// + "-" + (index + 1),  36               index,  37             };  38           });  39         let filecountchunk=chunklistcurr.length;  40         let ii=0;  41         chunklistcurr.forEach(element => {//分片传输  42           const formData = new FormData()  43           formData.append('file', element.chunk);  44           formData.append('index', element.index);  45           formData.append('name', element.name);  46           formData.append('size', element.size);  47           //formData.append('filecount', filecount);  48           axios({  49             method: 'post',  50             url: '/api/system/System/UploadFileAttachmentChunk?zhuti='+this.state.zhuti,  51             data: formData,  52             headers: { "Content-Type": "multipart/form-data"}  53           }).then(({data}) => {  54             if(data.code==200){  55               ii++;  56               if(ii==filecountchunk){//分块全部上传完成  57                 let indata={"name":chunklistcurr[0].name,"filecount":filecountchunk,"filename":filename  58                   }  59                 axios({//传输完成,通知拼接  60                   method: 'post',  61                   url: '/api/system/System/CombineChunkToFileBatch',  62                   data: indata,  63                   headers: { "Content-Type": "application/json"}  64                 }).then(({data}) => {  65                   if(data.code==200){  66                     let listbatchupload={}  67                     uploadsuccesslist_curr.push(listbatchupload);  68                     this.setState({uploadsuccesslist:uploadsuccesslist_curr});  69                     filecount_success++;  70                   }  71                   else if(data.code==202){  72                     window.location.href="/wellcome";  73                   }  74                   else{  75                     message.error("上传失败,请稍后重试!详情:"+data.desc);  76                     filecount_success++;  77                   }  78                 }).catch((err) =>{  79                     console.log(err);  80                     message.error("上传失败,请稍后重试!");  81                 }).finally(() =>{  82                   if(filecount_success==filecount){  83                     this.setState({uploadflag:true})  84                     message.success("全部上传完成,请进一步确认上传是否全部成功");  85                     this.setState({fileuploading:false,tipContent:"加载中..."});  86                   }  87                 })  88               }  89             }  90             else if(data.code==202){  91               window.location.href="/wellcome";  92             }  93             else{  94               message.error("上传失败,请稍后重试!详情:"+data.desc);  95               chunklistcurr.length=0;  96               return;  97             }  98           }).catch((err) =>{  99               console.log(err); 100               message.error("上传失败,请稍后重试!"); 101               return; 102           }).finally(() =>{ }) 103         }) 104       } 105     }); 106   } 107   catch(e){         108     console.log('catch-e:'+e) 109   } 110 }) 111 }
 1 //创建文件切片  2 createFileChunk = (file, size = 20*1024*1024) => {  3     const fileChunkList = [];  4     let cur = 0;  5     while (cur < file.size) {  6       fileChunkList.push({ file: file.slice(cur, cur + size), name: file.uid });//uid:文件唯一标识  7       cur += size;  8     }  9     return fileChunkList; 10 };

 注:本文代码已在项目中实用,有疑问欢迎指正。