完整 的Flex多文件上传实例
下面的例子展示了用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
public class UploadFile extends HttpServlet {
19
private static final long serialVersionUID = 5425836142860976977L;
20
21
/**
22
* Processes requests for both HTTP <code>GET</code> and <code>POST</code> methods.
23
* @param request servlet request
24
* @param response servlet response
25
*/
26
// 定义文件的上传路径
27
private String uploadPath = "d:\\files\\";
28
// 限制文件的上传大小
29
private int maxPostSize = 100 * 1024 * 1024; //最大100M
30
public UploadFile() {
31
super();
32
}
33
public void destroy() {
34
super.destroy();
35
}
36
protected void processRequest(HttpServletRequest request, HttpServletResponse response)
37
throws ServletException, IOException {
38
System.out.println("Access !");
39
response.setContentType("text/html;charset=UTF-8");
40
//保存文件到服务器中
41
DiskFileItemFactory factory = new DiskFileItemFactory();
42
factory.setSizeThreshold(4096);
43
ServletFileUpload upload = new ServletFileUpload(factory);
44
upload.setHeaderEncoding("utf-8");
45
upload.setSizeMax(maxPostSize);
46
try {
47
List fileItems = upload.parseRequest(request);
48
Iterator iter = fileItems.iterator();
49
while (iter.hasNext()) {
50
FileItem item = (FileItem) iter.next();
51
if (!item.isFormField()) {
52
String name = item.getName();
53
System.out.println(name);
54
try {
55
item.write(new File(uploadPath + name));
56
response.getWriter().write("上 传成功。");
57
} catch (Exception e) {
58
e.printStackTrace();
59
response.getWriter().write(e.getMessage());
60
}
61
}
62
}
63
} catch (FileUploadException e) {
64
e.printStackTrace();
65
response.getWriter().write(e.getMessage());
66
System.out.println(e.getMessage() + "结 束");
67
}
68
}
69
protected void doGet(HttpServletRequest request, HttpServletResponse response)
70
throws ServletException, IOException {
71
processRequest(request, response);
72
}
73
/**
74
* Handles the HTTP <code>POST</code> method.
75
* @param request servlet request
76
* @param response servlet response
77
*/
78
protected void doPost(HttpServletRequest request, HttpServletResponse response)
79
throws ServletException, IOException {
80
processRequest(request, response);
81
}
82
/**
83
* Returns a short description of the servlet.
84
*/
85
public String getServletInfo() {
86
return "Short description";
87
}
88
}

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

代码稍微有点多,请见谅。