下面的例子展示了用Flex上传文件的完整代码。
- 基本实现的功能:
- 一次选取多个文件上传
- 上传过程中显示每个文件的进度
- 如果是图片,可以上传之前进行预览
- 可以选择逐个文件 上传,也可以选择同时上传多个文件,这样就是对服务器压力稍微大一些
-
- 技术点:
- 闭包方法(在c#里,也叫匿名委托方法), 根据我的体会,如果不使用闭包方法,更新进度条会是一个比较麻烦的问题,除非另外编写一个类,这个问题稍后再研究
- DataGrid中需要用到itemRenderer,从而在每行都显示进度条和删除、取消按钮
-
- 软件环境
- Flex Builder 3
- Flash player 10
- Flash player 9 (特别说明:如果使用这个版本的flashPlayer,FileFerence没有load方法和data属性,也就无法实现本地预览图片,请去掉 load和data有关调用即可)
- 在Flex Builder 3中默认是Flash Player 9,只能自己修改一下配置文件,切换到10,方法请参考Targeting Flash Player 10
-
-
还是先看一下程序吧,稍后再看代码
程序演示
源码下载:
客户端代码:fileUpload.xml-------------------------------------------------------------------------------------------------
1
<?xml version="1.0" encoding="utf-8"?>
2
<mx:Application xmlns:mx="http://www.adobe.com/2006/mxml"
3
layout="vertical" horizontalAlign="left" fontSize="12"
4
initialize="init()"
5
viewSourceURL="srcview/index.html">
6
<mx:NumberFormatter id="filesizeFormatter" useThousandsSeparator="true"/>
7
<mx:Script>
8
<![CDATA[
9
import mx.events.CollectionEvent;
10
import mx.formatters.NumberFormatter;
11
import mx.formatters.CurrencyFormatter;
12
import mx.collections.ArrayCollection;
13
import mx.controls.Alert;
14
private var fileRefs: FileReferenceList = new FileReferenceList();
15
//这个地址是我测试用的服务器地址
16
private var urlrequest: URLRequest = new URLRequest("http://localhost:8080/abc/UploadFile");
17
[Bindable]
18
private var selectedFiles: ArrayCollection = new ArrayCollection([]);
19
private var singleThreadFiles: Array = [];
20
[Bindable]
21
private var useSingleThread: Boolean = true;
22
private function init(): void
23
{
24
Security.allowDomain("*");
25
fileRefs.addEventListener(Event.SELECT, fileSelectHandler);
26
fileRefs.addEventListener(IOErrorEvent.IO_ERROR, ioErrorHandler);
27
fileRefs.addEventListener(Event.COMPLETE, completeHandler);
28
addEventListener(IOErrorEvent.IO_ERROR, ioErrorHandler);
29
}
30
private function selectFile(): void
31
{
32
fileRefs.browse([new FileFilter("Images (*.jpg, *.jpeg, *.gif, *.png)", "*.jpg;*.jpeg;*.gif;*.png"),
33
new FileFilter("所有文件(*.*)", "*.*")
34
]);
35
}
36
private function fileSelectHandler(event: Event): void
37
{
38
for each (var f: FileReference in fileRefs.fileList)
39
{
40
selectedFiles.addItem(f);
41
}
42
}
43
private function uploadFile(): void
44
{
45
for each (var f: FileReference in selectedFiles)
46
{
47
try
48
{
49
f.upload(urlrequest);
50
}
51
catch (e: Error)
52
{
53
Alert.show(e.message);
54
}
55
}
56
}
57
private function singleThreadUploadFile(): void
58
{
59
//FIFO:逐个从列表中取出,进行同步上传
60
if (singleThreadFiles.length > 0)
61
{
62
var f: FileReference = singleThreadFiles.pop() as FileReference;
63
f.addEventListener(Event.COMPLETE, doSingleUploadFileComplete);
64
f.upload(urlrequest);
65
}
66
}
67
private function doSingleUploadFileComplete(event: Event): void
68
{
69
var f: FileReference = event.target as FileReference;
70
f.removeEventListener(Event.COMPLETE, doSingleUploadFileComplete);
71
singleThreadUploadFile();
72
}
73
private function ioErrorHandler(e:IOErrorEvent): void
74
{
75
Alert.show(e.text);
76
}
77
private function completeHandler(e: Event): void
78
{
79
img.source = e.target.data;
80
}
81
private function showImage(e: Event): void
82
{
83
var f: FileReference = (e.target as DataGrid).selectedItem as FileReference;
84
f.addEventListener(Event.COMPLETE, completeHandler);
85
f.load();
86
}
87
public function removeFile(f: FileReference): void
88
{
89
var index: int = selectedFiles.getItemIndex(f);
90
if (index != -1)
91
selectedFiles.removeItemAt(index);
92
}
93
]]>
94
</mx:Script>
95
<mx:VBox>
96
<mx:HBox width="100%">
97
<mx:Button id="selectFileButton" label="浏览
" click="selectFile()"/>
98
<mx:Box width="100%" horizontalAlign="right">
99
<mx:Button click="selectedFiles.removeAll();" label="清空"/>
100
</mx:Box>
101
</mx:HBox>
102
<mx:DataGrid id="files" dataProvider="{selectedFiles}" change="showImage(event)">
103
<mx:columns>
104
<mx:DataGridColumn width="150" headerText="文件名" dataField="name" />
105
<mx:DataGridColumn headerText="大小(字节)" dataField="size">
106
<mx:itemRenderer>
107
<mx:Component>
108
<mx:Label text="{outerDocument.filesizeFormatter.format(data.size)}" textAlign="right"/>
109
</mx:Component>
110
</mx:itemRenderer>
111
</mx:DataGridColumn>
112
<mx:DataGridColumn headerText="上传进度" width="300">
113
<mx:itemRenderer>
114
<mx:Component>
115
<mx:HBox fontSize="10" fontWeight="normal" fontThickness="1">
116
<mx:Script>
117
<![CDATA[
118
import flash.profiler.showRedrawRegions;
119
import mx.controls.Alert;
120
import mx.controls.ProgressBar;
121
private function initProgressBar(event: Event): void
122
{
123
//使progressbar与file关联,从而产生进度条
124
var pb: ProgressBar = event.target as ProgressBar;
125
pb.label = "%3%%";
126
pb.setProgress(0, 100);
127
var f: FileReference = data as FileReference;
128
//使用闭包方法,更新进度条
129
f.addEventListener(ProgressEvent.PROGRESS,
130
function(event: ProgressEvent): void
131
{
132
pb.setProgress(event.bytesLoaded, event.bytesTotal);
133
}
134
);
135
f.addEventListener(DataEvent.UPLOAD_COMPLETE_DATA,
136
function (event: DataEvent): void
137
{
138
//服务器端一定要返回数据,否则,这个方法就不起作用了
139
pb.label = event.data;
140
}
141
);
142
}
143
]]>
144
</mx:Script>
145
<mx:ProgressBar verticalCenter="true" width="100%" paddingLeft="5" paddingRight="5"
146
maximum="100" minimum="0" labelPlacement="center" mode="manual"
147
label="%3%%" textAlign="left"
148
creationComplete="initProgressBar(event)"/>
149
<mx:LinkButton label="Cancel">
150
<mx:click>
151
<![CDATA[
152
var f: FileReference = data as FileReference;
153
f.cancel();
154
]]>
155
</mx:click>
156
</mx:LinkButton>
157
<mx:LinkButton label="Delete">
158
<mx:click>
159
<![CDATA[
160
var f: FileReference = data as FileReference;
161
outerDocument.removeFile(f);
162
]]>
163
</mx:click>
164
</mx:LinkButton>
165
</mx:HBox>
166
</mx:Component>
167
</mx:itemRenderer>
168
</mx:DataGridColumn>
169
</mx:columns>
170
</mx:DataGrid>
171
</mx:VBox>
172
<mx:HBox>
173
<mx:Button label="上传">
174
<mx:click>
175
<![CDATA[
176
if (useSingleThread)
177
{
178
//逐个上传
179
singleThreadFiles = selectedFiles.toArray().concat();
180
singleThreadFiles.reverse();
181
singleThreadUploadFile();
182
}
183
else
184
{
185
//多个文件同时上传
186
uploadFile();
187
}
188
]]>
189
</mx:click>
190
</mx:Button>
191
<mx:CheckBox id="checkboxSingleThread" label="同时上传多个文件" selected="{!useSingleThread}"
192
change="useSingleThread = !checkboxSingleThread.selected"/>
193
</mx:HBox>
194
<mx:Image id="img" width="400" height="300"/>
195
</mx:Application>
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
服务器端代码:-----------------------------------------------------------------------------------------------------------
1
package com.java.test;
2
3
import java.io.File;
4
import java.io.IOException;
5
6
import java.util.Iterator;
7
import java.util.List;
8
9
import javax.servlet.ServletException;
10
import javax.servlet.http.HttpServlet;
11
import javax.servlet.http.HttpServletRequest;
12
import javax.servlet.http.HttpServletResponse;
13
14
import org.apache.commons.fileupload.FileItem;
15
import org.apache.commons.fileupload.FileUploadException;
16
import org.apache.commons.fileupload.disk.DiskFileItemFactory;
17
import org.apache.commons.fileupload.servlet.ServletFileUpload;
18
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
代码稍微有点多,请见谅。