一个Flex3多文件上传组件

最近在看《Flex3权威指南》,除了书中个别地方翻译的笔误外,确实是本好书,看的兴起,就写了这个多文件上传组件。

网上现成上传组件很多,有些写的很好,我的当然不能和别人那些牛人的相比,仅做学习交流之用,在代码组织和结构设计方面还有很多需要改进的地方,希望大家多提意见。

废话不多说,先看工作界面吧:

 

我的开发环境是Eclipse+Flex插件+Myeclipse(Myeclipse可有可无,这是我用来开发J2EE的),用MyEclipse7.5集成包的同志们安装Flex插件有困难的可以参考我前面的一篇文章:MyEclipse 7.5,MyEclipse 8.0中安装Flex插件。整个源文件的结构如下:

其实只要看flex_src和src两个目录就可以了。下面主要介绍下程序代码(至于怎样新建Flex Project,怎样下一步之类的就不再罗嗦了,实在不知道的自己Google去):flex_src 目录下是所有的Flex源代码,src下面的是后台的接收代码(java 的servlet)。com.havenliu.event.DeleteEvent.as是一个自定义的Flex事件类,用来删除单个附件。cpt目录下的deletebtn.mxml是一个自定义删除组件,很简单,里面就一个删除按钮,但附件完成上传后,改按钮变成灰色;最主要的东西都在MyUpload.mxml文件中。

?[Copy to clipboard] Download MyUpload.mxml
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
 
<?xml version="1.0" encoding="utf-8"?>
<mx:Application xmlns:mx="http://www.adobe.com/2006/mxml" layout="vertical" fontSize="13" creationComplete="init()" xmlns:e="cpt.*" >
<mx:Script>
	<![CDATA[
		import com.havenliu.event.DeleteEvent;
		import cpt.deletebtn;
		import mx.events.CloseEvent;
		import mx.collections.ArrayCollection;
		import mx.controls.Alert;
		import flash.profiler.showRedrawRegions;
        import mx.controls.ProgressBar;
 
        //最大上传文件数
		private var maxFiles:int=5;
		//最大上传文件大小(M)
		private var maxSize:Number=50;
		public var fileList:FileReferenceList = new FileReferenceList();
 
		private var fileSize:Number=0;
		//后台接受附件的地址,这里是一个servlet,你可以自己定义为jsp、php、asp、action等
		private var uploadurl:URLRequest = new URLRequest("http://localhost:8080/MyUpload/UploadFile");
		[Bindable]
		private var files:ArrayCollection=new ArrayCollection();
 
		private function init():void{
			//附件选择监听器
			fileList.addEventListener(Event.SELECT,selectHandler);
			//给“添加”按钮注册监听器
			browse.addEventListener(MouseEvent.CLICK,browseHandler);
			//删除附件按钮注册监听器
			deleteAll.addEventListener(MouseEvent.CLICK,resetHandler);
			buttonState();
		}
 
		private function selectHandler(event:Event):void
		{
			var countfiles:int=files.length+fileList.fileList.length;
			var countsize:Number=0;
			//计算总附件大小
			for each(var _file:FileReference in fileList.fileList)
			{
				countsize+=_file.size;
			}
			countsize+=fileSize;
			if(countfiles>maxFiles)
			{
				Alert.show("一次最大只能上传"+maxFiles+"个附件");
			}else if(countsize>maxSize*(1024*1024))
			{
				Alert.show("附件大小不能超过"+maxSize+"M");
			}else
			{
				for each(var file:FileReference in fileList.fileList)
				{
					if(!checkDitto(file))
					{
						files.addItem(file);
						refreshText();
						buttonState();
					}
				}
			}
		}
 
		private function browseHandler(event:Event):void
		{
			//这里没有过滤文件类型,即所有文件都可以上传,实际开发中,为了安全考虑可能需要过滤
			var fileType:FileFilter=new FileFilter("文件类型(*.*)","*.*");
			var allTypes:Array = new Array(fileType);				
			fileList.browse(allTypes);
		}
		private function resetHandler(event:Event):void
		{
			Alert.show("您确定要删除全部附件?","提示信息",Alert.YES|Alert.NO,fileGrid,alertHandler,null,Alert.NO);
			function alertHandler(event:CloseEvent):void
			{
				if(event.detail==Alert.YES)
				{
					files.removeAll();
					refreshText();
					buttonState();
				}
			}
		}
		//更新Text文本信息
		private function refreshText():void
		{
			//重新统计附件大小,将原来的信息清0
			fileSize=0;
			for(var i:int=0;i<files.length;i++)
			{
				fileSize+=FileReference(files[i]).size;
			}
			msg.text="共计"+files.length+"个附件,文件总大小:"+(fileSize/(1024*1024)).toString().slice(0,4)+"M (最大上传5个附件,总大小不超过50M)";
		}
		//控制按钮状态
		private function buttonState():void
		{
			if(files.length<1)
			{
				upload.enabled=false;
				deleteAll.enabled=false;
			}else
			{
				upload.enabled=true;
				deleteAll.enabled=true;
			}
			if(files.length>=maxFiles)
			{
				browse.enabled=false;
			}else
			{
				browse.enabled=true;
			}
		}
		private function uploadfile():void
		{
			if(files.length>0)
			{
				for(var i:int=0;i<files.length;i++)
				{
					var file:FileReference=files[i] as FileReference;
					try{
						file.addEventListener(Event.COMPLETE,uploadok);
//						 file.addEventListener(ProgressEvent.PROGRESS,uploadstart);
						file.upload(uploadurl);
					}catch(error:Error)
					{
						Alert.show("上传失败",error.message);
					}
				}
				//文件全部上传完成后,上传和全部删除按钮变为灰色
				upload.enabled=false;
				deleteAll.enabled=false;
				browse.enabled=false;
			}
		}
 
		//判断文件是否重复
		private function checkDitto(file:FileReference):Boolean
		{
			var result:Boolean=false;
			for (var i:int=0;i<files.length;i++)
			{
				var _file:FileReference=files[i];
				//如果选择文件的名字、大小和最后修改时间完全一样,则这两个文件重复
				if(file.name==_file.name||file.modificationDate==_file.modificationDate||file.size==_file.size)
				{
					result= true;
					break;
				}
				else
				{
					result= false;
				}
			}
			return result;
		}
		public  function deleteFile(data:Object):void
		{
			var indexNo:int=files.getItemIndex(data as FileReference);
			files.removeItemAt(indexNo);
			refreshText();
			buttonState();
		}
 
		public  function probar(event:Event,data:Object):void
		{
			var probar:ProgressBar=event.target as ProgressBar;
			probar.label = "%3%%";
            probar.setProgress(0, 100);
            var file:FileReference=data as FileReference;
            file.addEventListener(ProgressEvent.PROGRESS,
            	function(event: ProgressEvent): void
	                 {
	                     probar.setProgress(event.bytesLoaded, event.bytesTotal);
	                });
 
		}
		private function uploadok(event:Event):void
		{
			var file: FileReference = event.target as FileReference;
			file.removeEventListener(Event.COMPLETE,uploadok);
			trace("上载完成");
 
		}
//		private function uploadstart(event:Event):void
//		{
//			trace("上载开始");
//		}
		public function deletefile(event:DeleteEvent):void
		{
			var delfile:FileReference=event.file;
			deleteFile(delfile);
		}
 
	]]>
</mx:Script>
	<mx:Panel width="500" height="300" layout="absolute" title="多文件上传组件">
			<mx:VBox width="100%" height="100%" x="0" y="0">
					<mx:DataGrid id="fileGrid" width="100%" dataProvider="{files}">
						<mx:columns>
							<mx:DataGridColumn headerText="文件名" dataField="name" />
							<mx:DataGridColumn width="80" headerText="大小(字节)" dataField="size"/>
							<mx:DataGridColumn width="120" headerText="上传进度" dataField="loadRate" sortable="false" ><mx:itemRenderer>
								<mx:Component>
								<mx:HBox fontSize="10" fontWeight="normal" fontThickness="1">
								<mx:ProgressBar verticalCenter="true" width="100%" paddingLeft="5" paddingRight="5"
                                    maximum="100" minimum="0" labelPlacement="center" mode="manual"
                                   label="%3%%" textAlign="left" creationComplete="outerDocument.probar(event,data)"/>
                                   </mx:HBox>
								</mx:Component>
								</mx:itemRenderer>
							</mx:DataGridColumn>
							<mx:DataGridColumn    headerText="删除" sortable="false" >
							<mx:itemRenderer> 
								<mx:Component> 
								<e:deletebtn  tarfile="{data as FileReference}" delFile="outerDocument.deletefile(event)">
								</e:deletebtn>
								</mx:Component> 
								</mx:itemRenderer>
							</mx:DataGridColumn>
						</mx:columns>
					</mx:DataGrid>
					<mx:HBox width="100%" height="39">
							<mx:Spacer/>
							<mx:Button  id="browse" label="添加..." textAlign="right"/>
							<mx:Button id="upload" label="上传" click="uploadfile()" textAlign="right"/>
							<mx:Button id="deleteAll" label="全部删除" textAlign="right"/>
					</mx:HBox>
					<mx:Text id="msg" text="共计0个附件,文件总大小:0M (最大上传5个附件,总大小不超过50M)" fontSize="12" fontFamily="Arial"/>
			</mx:VBox>
	</mx:Panel>
 
</mx:Application>

DeleteEvent.as的源代码:

?[Copy to clipboard] Download DeleteEvent.as
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
package com.havenliu.event
{
	import flash.events.Event;
	import flash.net.FileReference;
 
	public class DeleteEvent extends Event
	{
		//当前要删除的附件
		public var file:FileReference;
 
		public function DeleteEvent(type:String,file:FileReference)
		{
			super(type);
			this.file=file;
		}
	}
}

deletebtn.mxml组件的源代码:

?[Copy to clipboard] Download deletebtn.mxml
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
<?xml version="1.0" encoding="utf-8"?>
<mx:Canvas xmlns:mx="http://www.adobe.com/2006/mxml" creationComplete="btnlis()">
 <mx:Metadata>
        [Event(name="delFile", type="com.havenliu.event.DeleteEvent")]
 </mx:Metadata>
 
<mx:Script>
	<![CDATA[
	import com.havenliu.event.DeleteEvent;
		public var tarfile:FileReference;
 
		internal function deleteFile():void
		{
			var delevent:DeleteEvent=new DeleteEvent("delFile",tarfile);
			this.dispatchEvent(delevent);
		} 
		private function comlis(event:Event):void
		{
			deletebutton.enabled=false;
		}
		private function btnlis():void
		{
			//给当前附件注册监听器,如果附件已经上传完成,则将删除按钮的enabled设置为false(不可操作)
			tarfile.addEventListener(Event.COMPLETE,comlis);
		}
 
	]]>
</mx:Script>
	<mx:Button id="deletebutton" label="删除" click="deleteFile()" >
	</mx:Button>
</mx:Canvas>

后台接收文件的源代码。这里用的是java做的后台。用Servlet接收的。你可以用php或者asp做后台都无所谓,选择自己熟悉的就行:

?[Copy to clipboard] Download UploadFile.java

最后别忘了在web.xml中注册你的servlet。
到这里基本就差不多了,代码中的注释基本能看懂了。人品不是很差的话应该能直接跑起来了。源代码包就不放上来了,主要是没地方上传,那些网盘什么的我不太喜欢用。需要的朋友们留下邮箱我发给你们。

PS:最后叽歪两句:现在找个满意的图床真难啊,国内的基本不敢用,很多不稳定,开始还好,最后那天就悄然无声的关服务器了,让你哭都哭不出来。稳定的很多又不支持外链,类似163之类的;那些支持的外链、也勉强能算的上稳定的又有很多莫名奇妙的规矩,限制大小和流量啊(这还好,还勉强能接受),自做主张的给你的图片加水印(最不能接收这点)什么。国外的好的图床到是蛮多,比如google的picasa 、雅虎的flickr什么的,这些都用过,但最后都在伟大的GFW下壮烈牺牲了,就算有些坚持到现在还能用,但谁也不敢保证明天早上我打开的我的blog不看见红叉叉。犹豫再三。国外的也不敢用了。。。。。。在折腾了两天后,终于决定把文章里的图片就放在我自己的空间里,从长远来考虑这不太好,但这也是目前最好的选择了。。。。。。。

 

 

http://www.havenliu.com/web/327.html

你可能感兴趣的:(一个Flex3多文件上传组件)