Flex4/Flash多檔案上傳(帶進度條)例項分享

Cheng發表於2014-03-07

要求

    • 必備知識

      本文要求基本瞭解 Adobe Flex程式設計知識和JAVA基礎知識。

    • 開發環境

      MyEclipse10/Flash Builder4.6/Flash Player11及以上

    • 演示地址

      演示地址 資料下載

 

FLASH檔案上傳和傳統的HTML檔案上傳,能實現多檔案上傳、大檔案上傳,和上傳前預覽。

當然HTML5也能實現上述功能,這裡就不多說了,有時間我在做一個例項和大家分享一下。

下面介紹一下 百度圖片 基於FLASH檔案上傳工具截圖:

2014-03-07_052617

 

MultiFile Upload 上傳外掛介紹:

2014-03-07_071021

 

官方DEMO:

2014-03-07_071101

 

下面是對MultiFile Upload 外掛的UI自定義和程式碼的翻譯:

介面:

2014-03-07_100719

自定義UI元件:  FlashFileUpload.mxml
<?xml version="1.0" encoding="utf-8"?>
<s:Application xmlns:fx="http://ns.adobe.com/mxml/2009" 
               xmlns:s="library://ns.adobe.com/flex/spark" 
               xmlns:mx="library://ns.adobe.com/flex/mx" minWidth="955" minHeight="600"
              backgroundColor="#333333" horizontalCenter="0" verticalCenter="0"
              creationComplete="initApp()">
    <fx:Declarations>
        
    </fx:Declarations>
    <fx:Script>
        <![CDATA[
            
            import com.newmediateam.fileIO.MultiFileUpload;
            
            
            import flash.media.Sound;
            import flash.media.SoundChannel;
            import flash.net.FileFilter;
            import flash.net.URLVariables;
            
            import mx.controls.Alert;
            
            import mx.core.SoundAsset;
            
            public var multiFileUpload:MultiFileUpload;
            
            // 傳送完成音樂
            [Embed(source="assets/audio/Ding.mp3")]
            public var soundClass:Class;
            public var snd:SoundAsset = new soundClass() as SoundAsset;
            public var sndChannel:SoundChannel;
            
            // 設定檔案過濾器
            public var imageTypes:FileFilter = new FileFilter("Images (*.jpg; *.jpeg; *.gif; *.png)" ,"*.jpg; *.jpeg; *.gif; *.png");
            public var videoTypes:FileFilter = new FileFilter("Flash Video Files (*.flv)","*.flv");
            public var documentTypes:FileFilter = new FileFilter("Documents (*.pdf), (*.doc), (*.rtf), (*.txt)",("*.pdf; *.doc; *.rtf, *.txt"));
            
            // 將檔案過濾器裝載如陣列 遞給MultiFileUpload
            public var filesToFilter:Array = new Array(imageTypes,videoTypes,documentTypes);
            
            public var uploadDestination:String = "http://www.li-cheng.cn";  // 修改服務端上傳控制器
            
            public function initApp():void{
                
                var postVariables:URLVariables = new URLVariables;
                postVariables.projectID = 55;
                postVariables.test ="Hello World";    
                
                multiFileUpload = new MultiFileUpload(
                    filesDG,
                    browseBTN,
                    clearButton,
                    delButton,
                    upload_btn,
                    progressbar,
                    uploadDestination,
                    postVariables,
                    11534336,
                    filesToFilter
                );
                
                multiFileUpload.addEventListener(Event.COMPLETE,uploadsfinished);  //事件有分配
                
            }
            
            public function uploadsfinished(event:Event):void{
                
                sndChannel=snd.play();  //播放音訊檔案
                
            }
            

        ]]>
    </fx:Script>
    
    
    <s:Group horizontalCenter="0" top="100"  width="708" height="408" >
        <s:BitmapImage source="@Embed('/assets/images/RasterizedItems.png')"   /> <!--背景圖片-->
        <s:SkinnableContainer horizontalCenter="0" verticalCenter="0"  width="638" height="308" skinClass="skins.SkinnableContainer">
             <s:layout>
                 <s:VerticalLayout paddingLeft="15" paddingRight="23" paddingTop="15" paddingBottom="23" />
             </s:layout>
            <!--資料列表-->
             <s:DataGrid id="filesDG" requestedRowCount="4" rowHeight="40"   width="100%" height="200"   skinClass="skins.DG" >
                <!-- <s:columns>
                     <s:ArrayList>
                         <s:GridColumn dataField="a" headerText="#" headerRenderer="components.GridHeaderRenderer"  itemRenderer="components.GridItemRenderer"></s:GridColumn>
                         <s:GridColumn dataField="b" headerText="歌曲" headerRenderer="components.GridHeaderRenderer"  itemRenderer="components.GridItemRenderer"></s:GridColumn>
                     </s:ArrayList>
                 </s:columns>-->
             </s:DataGrid>
            <s:HGroup width="65%">
                <!--進度條-->
                <mx:ProgressBar 
                    id="progressbar"
                    width="100%" 
                    labelPlacement="right"
                    barSkin="skins.ProgressBar.CustomProgressSkin"
                    trackSkin="skins.ProgressBar.CustomProgressBarTrackSkin"
                    color="0xFFFFFF"
                    minimum="0" 
                    visible="true"
                    maximum="100" 
                    label="CurrentProgress 0%" 
                    direction="right"
                    mode="manual" 
                    />
            </s:HGroup>
            <!--按鈕們-->
            <s:HGroup gap="10" paddingTop="10">
                <s:Button id="browseBTN" skinClass="skins.buttonSkin4" label="瀏覽" fontFamily="微軟雅黑"/>
                <s:Button id="upload_btn" skinClass="skins.buttonSkin5" label="上傳" fontFamily="微軟雅黑"/>
                <s:Button  id="delButton" skinClass="skins.buttonSkin6" label="移除" fontFamily="微軟雅黑"/>
                <s:Button id="clearButton" skinClass="skins.buttonSkin6" label="移除全部" fontFamily="微軟雅黑"/>
            </s:HGroup>
        </s:SkinnableContainer>
    </s:Group>
    
</s:Application>

 

主程式程式碼:  MultiFileUpload.as
//    例子:
//    multiFileUpload = new MultiFileUpload(
//          filesDG,    DataGrid元件 
//          browseBTN, 瀏覽按鈕        
//          clearButton, 清楚全部    
//          delButton,     清楚選中    
//          upload_btn,     上傳按鈕    
//          progressbar,  進度條
//          "http://[Your Server Here]/MultiFileUpload/upload.cfm",   上傳地址 控制器
//          postVariables,  上傳引數     
//          350000,         最大檔案大小      0 (零)值=沒有檔案限制
//          filesToFilter     檔案過濾陣列
//           );


package com.newmediateam.fileIO {

    //倒入包
    import components.GridHeaderRenderer;
    import components.GridItemRenderer;
    
    import flash.events.*;
    import flash.net.FileFilter;
    import flash.net.FileReference;
    import flash.net.FileReferenceList;
    import flash.net.URLRequest;
    import flash.net.URLVariables;
    
    import mx.collections.ArrayCollection;
    import mx.collections.ArrayList;
    import mx.controls.Alert;
    import mx.controls.ProgressBar;
    import mx.controls.ProgressBarMode;
    import mx.core.ClassFactory;
    import mx.events.CollectionEvent;
    
    import spark.components.Button;
    import spark.components.DataGrid;
    import spark.components.gridClasses.GridColumn;

    
    
    public class MultiFileUpload {
    
        
        
        //UI 變數
        private var _datagrid:DataGrid;
        private var _browsebutton:Button;
        private var _remselbutton:Button;
        private var _remallbutton:Button;
        private var _uploadbutton:Button;
        private var _progressbar:ProgressBar;
        private var _testButton:Button;

        //DataGrid 列
        private var _nameColumn:GridColumn;
        private var _typeColumn:GridColumn;
        private var _sizeColumn:GridColumn;
        private var _creationDate:GridColumn;
        private var _modificationDate:GridColumn;
        private var _progressColumn:GridColumn;
        private var _columns:ArrayList;
        
        // 檔案參考變數
        [Bindable]
        private var _files:ArrayCollection;
        private var _fileref:FileReferenceList  //FileReferenceList 類提供了讓使用者選擇一個或多個要上載的檔案的方法。
        private var _file:FileReference;  //FileReference 類提供了在使用者計算機和伺服器之間上載和下載檔案的方法
        private var _uploadURL:URLRequest;
        private var  _totalbytes:Number;
        
        // 檔案過濾陣列
        private var _filefilter:Array;

        //配置變數
        private var _url:String; //  檔案上傳URL
        private var _maxFileSize:Number; //允許上次的最大檔案大小 單位位元組
        private var _variables:URLVariables; // 上傳變數 類似 ?a=hello&b=world
        
        //構造器  
        public function MultiFileUpload(
                                        dataGrid:DataGrid,
                                        browseButton:Button,
                                        removeAllButton:Button,
                                        removeSelectedButton:Button,
                                        uploadButton:Button,
                                        progressBar:ProgressBar,
                                        url:String,
                                        variables:URLVariables,
                                        maxFileSize:Number,
                                        filter:Array
                                        ){
            _datagrid = dataGrid;
            _browsebutton = browseButton;
            _remallbutton = removeAllButton;
            _remselbutton = removeSelectedButton;            
            _uploadbutton = uploadButton;
            _url = url;
            _progressbar = progressBar;
            _variables = variables;
            _maxFileSize = maxFileSize;
            _filefilter = filter;
            init();   //呼叫初始化話函式
        }
        
        //初始化函式
        private function init():void{
            
            // 設定檔案 ArrayCollection 和  檔案處理變數
            _files = new ArrayCollection();
            _fileref = new FileReferenceList;
            _file = new FileReference;
            
            // 設定總位元組數
            _totalbytes = 0;
            
            // 給UI元件監聽事件
            _browsebutton.addEventListener(MouseEvent.CLICK, browseFiles);
            _uploadbutton.addEventListener(MouseEvent.CLICK,uploadFiles);
            _remallbutton.addEventListener(MouseEvent.CLICK,clearFileCue);
            _remselbutton.addEventListener(MouseEvent.CLICK,removeSelectedFileFromCue);
            _fileref.addEventListener(Event.SELECT, selectHandler);
            _files.addEventListener(CollectionEvent.COLLECTION_CHANGE,popDataGrid);  //集合資料變化是監聽此函式
            
            // 設定進度條引數
            _progressbar.mode = "manual"; // 指定用於更新進度欄的方法。
            _progressbar.label = "";
            
            //設定按鈕元件
            _uploadbutton.enabled = false;
            _remselbutton.enabled = false;
            _remallbutton.enabled = false;
            
            
            // 設定 DataGrid 控制元件
            _nameColumn = new GridColumn;
            _typeColumn = new GridColumn;
            _sizeColumn = new GridColumn;
                
            _nameColumn.dataField = "name";
            _nameColumn.headerText= "檔案";
            _nameColumn.headerRenderer=new ClassFactory(GridHeaderRenderer);
            
            _typeColumn.dataField = "type";
            _typeColumn.headerText = "型別";
            _typeColumn.width = 80;
            _typeColumn.headerRenderer=new ClassFactory(GridHeaderRenderer);
            
            _sizeColumn.dataField = "size";
            _sizeColumn.headerText = "檔案大小";
            _sizeColumn.labelFunction = bytesToKilobytes as Function; //Label處理函式
            _sizeColumn.width = 150;
            _sizeColumn.headerRenderer=new ClassFactory(GridHeaderRenderer);
            
            _columns = new ArrayList([_nameColumn,_typeColumn,_sizeColumn]);
            _datagrid.columns=_columns;
            
            
            _datagrid.sortableColumns = false; //排序
            _datagrid.dataProvider = _files;  //資料繫結
          
            
            // 設定URL請求物件和地址
            _uploadURL = new URLRequest;
            _uploadURL.url = _url;
            _uploadURL.method = "POST";  //設定請求方式     可以為POST和GET  ..
            
            _uploadURL.data = _variables; //變數
            _uploadURL.contentType = "multipart/form-data"; //請求型別宣告 如果要上傳二進位制資料這個必須 
            
            
        }
        
        /********************************************************
        *     私有方法                                                                                               *
        ********************************************************/
        
        
        //  流量檔案  多檔案流量
        private function browseFiles(event:Event):void{                    
                _fileref.browse(_filefilter);               
       }

        // 上傳檔案
        private function uploadFiles(event:Event):void{
           
            if (_files.length > 0){
                _file = FileReference(_files.getItemAt(0));    
                _file.addEventListener(Event.OPEN, openHandler);  //前置操作
                _file.addEventListener(ProgressEvent.PROGRESS, progressHandler);
                _file.addEventListener(Event.COMPLETE, completeHandler);
                _file.addEventListener(SecurityErrorEvent.SECURITY_ERROR,securityErrorHandler);//當對 FileReference.upload() 或 FileReference.download() 方法的呼叫嘗試將檔案上載到呼叫方安全沙箱外部的伺服器,或是從呼叫方安全沙箱外部的伺服器上下載檔案時進行排程。
                _file.addEventListener(HTTPStatusEvent.HTTP_STATUS,httpStatusHandler);//當上載失敗並且存在可用來描述失敗的 HTTP 狀態程式碼時排程。
                _file.addEventListener(IOErrorEvent.IO_ERROR,ioErrorHandler);//當上載或下載失敗時排程。
                _file.upload(_uploadURL);
                 setupCancelButton(true);
            }
        }
        
        // 刪除選定的檔案
        private function removeSelectedFileFromCue(event:Event):void{
           
            if (_datagrid.selectedIndex >= 0){
                    _files.removeItemAt( _datagrid.selectedIndex);
            }
        }


         //  刪除全部檔案
        private function clearFileCue(event:Event):void{
            _nameColumn.itemRenderer=null;
            _typeColumn.itemRenderer=null;
            _sizeColumn.itemRenderer=null;
            _files.removeAll();
        }
        
        // 取消當前檔案上傳
        private function cancelFileIO(event:Event):void{
            
            _file.cancel();
            setupCancelButton(false);
            checkCue();
            
        }    
    
       


        //檔案型別列  label處理函式
        private function bytesToKilobytes(data:Object,blank:Object):String {
            var kilobytes:String;
            kilobytes = String(Math.round(data.size/ 1024)) + ' kb';
            return kilobytes
        }
        
        
       
        // 設定進度條Labe值
        private function getByteCount():void{
            var i:int;
            _totalbytes = 0;
                for(i=0;i < _files.length;i++){
                _totalbytes +=  _files[i].size;
                }
            _progressbar.label = "檔案: "+  _files.length+ "大小: " + Math.round(_totalbytes/1024) + " kb"
        }        
        
       
        //檢查檔案不超過maxFileSize為|如果_maxFileSize == 0沒有檔案限制設定
        private function checkFileSize(filesize:Number):Boolean{
      
            var r:Boolean = false;
                //if  filesize greater then _maxFileSize
                if (filesize > _maxFileSize){
                    r = false;
                    trace("false");
                    }else if (filesize <= _maxFileSize){
                    r = true;
                    trace("true");
                }
                
                if (_maxFileSize == 0){
                r = true;
                }
           
            return r;
        }
        
      
        // 重新設定進度條
        private function resetProgressBar():void{
        
                  _progressbar.label = "";
                 _progressbar.maximum = 0;
                 _progressbar.minimum = 0;
        }
        
        // reset form item elements 重置所有的元素
        private function resetForm():void{
            _uploadbutton.enabled = false;
            _uploadbutton.addEventListener(MouseEvent.CLICK,uploadFiles);
            _uploadbutton.label = "上傳";
            _progressbar.maximum = 0;
            _totalbytes = 0;
            _progressbar.label = "";
            _remselbutton.enabled = false;
            _remallbutton.enabled = false;
            _browsebutton.enabled = true;
        }
       
        
        //每當_FILES的ArrayCollection改變這個函式被呼叫,以確保資料網格的資料的一致
        private function popDataGrid(event:CollectionEvent):void{                
            getByteCount();
            checkCue();
        }
        
       // enable or disable upload and remove controls based on files in the cue;   
        //啟用上傳和清楚按鈕
        private function checkCue():void{
             if (_files.length > 0){
                _uploadbutton.enabled = true;
                _remselbutton.enabled = true;
                _remallbutton.enabled = true;            
             }else{
                resetProgressBar();
                _uploadbutton.enabled = false;     
             }    
        }

        // toggle upload button label and function to trigger file uploading or upload cancelling
        // 上傳按鈕和取消按鈕的切換 和功能的切換
        private function setupCancelButton(x:Boolean):void{
            if (x == true){
                _uploadbutton.label = "取消";
                _browsebutton.enabled = false;
                _remselbutton.enabled = false;
                _remallbutton.enabled = false;
                _uploadbutton.addEventListener(MouseEvent.CLICK,cancelFileIO);        
            }else if (x == false){
                _uploadbutton.removeEventListener(MouseEvent.CLICK,cancelFileIO);
                 resetForm();
            }
        }
        

       /*********************************************************
       *  File IO Event Handlers                                *
       *********************************************************/
      
        //  called after user selected files form the browse dialouge box.
        //  檔案被選中後執行的響應函式
        private function selectHandler(event:Event):void {
            var i:int;
            var msg:String ="";
            var dl:Array = [];                          
                for (i=0;i < event.currentTarget.fileList.length; i ++){
                    if (checkFileSize(event.currentTarget.fileList[i].size)){
                    _files.addItem(event.currentTarget.fileList[i]);
                    trace("under size " + event.currentTarget.fileList[i].size);
                    }  else {
                    dl.push(event.currentTarget.fileList[i]);
                    trace(event.currentTarget.fileList[i].name + " too large");
                    }
                    
                    
                    _nameColumn.itemRenderer=new ClassFactory(GridItemRenderer);
                    _typeColumn.itemRenderer=new ClassFactory(GridItemRenderer);
                    _sizeColumn.itemRenderer=new ClassFactory(GridItemRenderer);
                    _sizeColumn.labelFunction = bytesToKilobytes as Function; //Label處理函式
                    
                }                
                if (dl.length > 0){
                    for (i=0;i<dl.length;i++){
                    msg += String(dl[i].name + " 檔案過大. \n");
                    }
                    mx.controls.Alert.show(msg + "檔案最大為: " + Math.round(_maxFileSize / 1024) + " kb","檔案過大",4,null).clipContent;
                }        
        }        
        
    
        // 檔案被開啟  上傳之前的響應函式
        private function openHandler(event:Event):void{
            trace('openHandler triggered');
            _files;
        }
        
      
          //檔案上傳被上傳的每個檔案的過程中呼叫|我們用這個來養活進度條的資料
        private function progressHandler(event:ProgressEvent):void {        
            _progressbar.setProgress(event.bytesLoaded,event.bytesTotal);  //設定進度條的狀態
            _progressbar.label = "Uploading " + Math.round(event.bytesLoaded / 1024) + " kb of " + Math.round(event.bytesTotal / 1024) + " kb " + (_files.length - 1) + "剩餘";
        }

      
        //所謂的後一個檔案已被successully上傳|我們利用這一點來檢查是否有任何檔案留下來上傳和如何處理它
        //上傳完成
        private function completeHandler(event:Event):void{
          
            _files.removeItemAt(0); //移除集合中的第0號元素
            if (_files.length > 0){
                _totalbytes = 0;
                uploadFiles(null);
            }else{
                setupCancelButton(false);
                 _progressbar.label = "上傳完成";
                 var uploadCompleted:Event = new Event(Event.COMPLETE);  //完成時建立一個事件 
                 
                dispatchEvent(uploadCompleted); //把事件分配出去
            }
        }    
          
      
        private function ioErrorHandler(event:IOErrorEvent):void{
            //trace('And IO Error has occured:' +  event);
            mx.controls.Alert.show(String(event),"ioError",0);
        }    
      
        private function securityErrorHandler(event:SecurityErrorEvent):void{
            mx.controls.Alert.show(String(event),"Security Error",0);
        }
        
       
        private function cancelHandler(event:Event):void{
            trace('cancelled');
        }
        
        private function httpStatusHandler(event:HTTPStatusEvent):void {
            if (event.status != 200){
                mx.controls.Alert.show(String(event),"Error",0);
            }
        }

        
    }
}

 

演示地址: http://www.li-cheng.cn/demo/FlashFileUpload/FlashFileUpload.html

資料下載:    http://pan.baidu.com/share/link?shareid=1217875474&uk=1545675865

作者:Li-Cheng
本文版權歸作者和部落格園共有,歡迎轉載,但未經作者同意必須保留此段宣告,且在文章頁面明顯位置給出原文連線,否則保留追究法律責任的權利。

相關文章