完整的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<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>
服务器端代码:-----------------------------------------------------------------------------------------------------------
1package com.java.test;
2
3import java.io.File;
4import java.io.IOException;
5
6import java.util.Iterator;
7import java.util.List;
8
9import javax.servlet.ServletException;
10import javax.servlet.http.HttpServlet;
11import javax.servlet.http.HttpServletRequest;
12import javax.servlet.http.HttpServletResponse;
13
14import org.apache.commons.fileupload.FileItem;
15import org.apache.commons.fileupload.FileUploadException;
16import org.apache.commons.fileupload.disk.DiskFileItemFactory;
17import org.apache.commons.fileupload.servlet.ServletFileUpload;
18public 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
3import java.io.File;
4import java.io.IOException;
5
6import java.util.Iterator;
7import java.util.List;
8
9import javax.servlet.ServletException;
10import javax.servlet.http.HttpServlet;
11import javax.servlet.http.HttpServletRequest;
12import javax.servlet.http.HttpServletResponse;
13
14import org.apache.commons.fileupload.FileItem;
15import org.apache.commons.fileupload.FileUploadException;
16import org.apache.commons.fileupload.disk.DiskFileItemFactory;
17import org.apache.commons.fileupload.servlet.ServletFileUpload;
18public 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}
代码稍微有点多,请见谅。