完整的Flex多文件上传实例

下面的例子展示了用Flex上传文件的完整代码。

  1. 基本实现的功能:
    • 一次选取多个文件上传
    • 上传过程中显示每个文件的进度
    • 如果是图片,可以上传之前进行预览
    • 可以选择逐个文件上传,也可以选择同时上传多个文件,这样就是对服务器压力稍微大一些
  2. 技术点:
    • 闭包方法(在c#里,也叫匿名委托方法),根据我的体会,如果不使用闭包方法,更新进度条会是一个比较麻烦的问题,除非另外编写一个类,这个问题稍后再研究
    • DataGrid中需要用到itemRenderer,从而在每行都显示进度条和删除、取消按钮
  3. 软件环境
    • 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

客户端代码: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>

 

服务器端代码:-----------------------------------------------------------------------------------------------------------


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}
 

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

posted @ 2009-08-03 20:30  静候良机  阅读(26411)  评论(1编辑  收藏  举报