通过 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 }
注:本文代码已在项目中实用,有疑问欢迎指正。
我有一个Ruby程序,它使用rubyzip压缩XML文件的目录树。gem。我的问题是文件开始变得很重,我想提高压缩级别,因为压缩时间不是问题。我在rubyzipdocumentation中找不到一种为创建的ZIP文件指定压缩级别的方法。有人知道如何更改此设置吗?是否有另一个允许指定压缩级别的Ruby库? 最佳答案 这是我通过查看rubyzip内部创建的代码。level=Zlib::BEST_COMPRESSIONZip::ZipOutputStream.open(zip_file)do|zip|Dir.glob("**/*")d
我试图在一个项目中使用rake,如果我把所有东西都放到Rakefile中,它会很大并且很难读取/找到东西,所以我试着将每个命名空间放在lib/rake中它自己的文件中,我添加了这个到我的rake文件的顶部:Dir['#{File.dirname(__FILE__)}/lib/rake/*.rake'].map{|f|requiref}它加载文件没问题,但没有任务。我现在只有一个.rake文件作为测试,名为“servers.rake”,它看起来像这样:namespace:serverdotask:testdoputs"test"endend所以当我运行rakeserver:testid时
我的目标是转换表单输入,例如“100兆字节”或“1GB”,并将其转换为我可以存储在数据库中的文件大小(以千字节为单位)。目前,我有这个:defquota_convert@regex=/([0-9]+)(.*)s/@sizes=%w{kilobytemegabytegigabyte}m=self.quota.match(@regex)if@sizes.include?m[2]eval("self.quota=#{m[1]}.#{m[2]}")endend这有效,但前提是输入是倍数(“gigabytes”,而不是“gigabyte”)并且由于使用了eval看起来疯狂不安全。所以,功能正常,
Rails2.3可以选择随时使用RouteSet#add_configuration_file添加更多路由。是否可以在Rails3项目中做同样的事情? 最佳答案 在config/application.rb中:config.paths.config.routes在Rails3.2(也可能是Rails3.1)中,使用:config.paths["config/routes"] 关于ruby-on-rails-Rails3中的多个路由文件,我们在StackOverflow上找到一个类似的问题
对于具有离线功能的智能手机应用程序,我正在为Xml文件创建单向文本同步。我希望我的服务器将增量/差异(例如GNU差异补丁)发送到目标设备。这是计划:Time=0Server:hasversion_1ofXmlfile(~800kiB)Client:hasversion_1ofXmlfile(~800kiB)Time=1Server:hasversion_1andversion_2ofXmlfile(each~800kiB)computesdeltaoftheseversions(=patch)(~10kiB)sendspatchtoClient(~10kiBtransferred)Cl
我正在寻找执行以下操作的正确语法(在Perl、Shell或Ruby中):#variabletoaccessthedatalinesappendedasafileEND_OF_SCRIPT_MARKERrawdatastartshereanditcontinues. 最佳答案 Perl用__DATA__做这个:#!/usr/bin/perlusestrict;usewarnings;while(){print;}__DATA__Texttoprintgoeshere 关于ruby-如何将脚
使用带有Rails插件的vim,您可以创建一个迁移文件,然后一次性打开该文件吗?textmate也可以这样吗? 最佳答案 你可以使用rails.vim然后做类似的事情::Rgeneratemigratonadd_foo_to_bar插件将打开迁移生成的文件,这正是您想要的。我不能代表textmate。 关于ruby-使用VimRails,您可以创建一个新的迁移文件并一次性打开它吗?,我们在StackOverflow上找到一个类似的问题: https://sta
好的,所以我的目标是轻松地将一些数据保存到磁盘以备后用。您如何简单地写入然后读取一个对象?所以如果我有一个简单的类classCattr_accessor:a,:bdefinitialize(a,b)@a,@b=a,bendend所以如果我从中非常快地制作一个objobj=C.new("foo","bar")#justgaveitsomerandomvalues然后我可以把它变成一个kindaidstring=obj.to_s#whichreturns""我终于可以将此字符串打印到文件或其他内容中。我的问题是,我该如何再次将这个id变回一个对象?我知道我可以自己挑选信息并制作一个接受该信
我正在编写一个小脚本来定位aws存储桶中的特定文件,并创建一个临时验证的url以发送给同事。(理想情况下,这将创建类似于在控制台上右键单击存储桶中的文件并复制链接地址的结果)。我研究过回形针,它似乎不符合这个标准,但我可能只是不知道它的全部功能。我尝试了以下方法:defauthenticated_url(file_name,bucket)AWS::S3::S3Object.url_for(file_name,bucket,:secure=>true,:expires=>20*60)end产生这种类型的结果:...-1.amazonaws.com/file_path/file.zip.A
我注意到像bundler这样的项目在每个specfile中执行requirespec_helper我还注意到rspec使用选项--require,它允许您在引导rspec时要求一个文件。您还可以将其添加到.rspec文件中,因此只要您运行不带参数的rspec就会添加它。使用上述方法有什么缺点可以解释为什么像bundler这样的项目选择在每个规范文件中都需要spec_helper吗? 最佳答案 我不在Bundler上工作,所以我不能直接谈论他们的做法。并非所有项目都checkin.rspec文件。原因是这个文件,通常按照当前的惯例,只