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

控件引用
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 };
注:本文代码已在项目中实用,有疑问欢迎指正。
漫思

浙公网安备 33010602011771号