Flex Multi-URLLoader with For Loop

摘要:Flex Multi-URLLoader with For Loop

最近開始研究關於 Adobe Flex 與 ActionScript 3,對於它一些相關 Class 的組成架構,到最近才有所突破,不過或多或少有遇到一些小問題,
這次主要是說明關於 URLLoader 或 URLStream 對於一個以上的檔案要做下載的同時會遇到的問題,其情境的說明我用下列小圖簡單說明一下:
繪圖1
 
1. 遠端 Server會擺放一個要下載檔案的清單,透過 XML來加以定義。
2. 透過 URLLoader下載 XML檔到自行撰寫的 Flex 程式。(Custom Application)。
3. 透過 Custom Application 進行 XML拆解將XML中列舉需要下載的檔案舉出來。
4. 取出的檔案名稱與路徑在進行下載的動作。
 
 
這一張圖,主要是說明如上四點,不過在此仍需要強調,XML、MP3 都是放在 Server 端的,只有在拆解掉 XML 清單之後,透過 Download 的方式
才會真的寫入到 Client 端。因此,這個程式主要是說明一個簡單的 Client-Server之間檔案要取檔案之間的問題而已。
不過,過去在撰寫 .NET程式的時候,透過 ASP.NET 我可以直接呼叫 Stream 的 Class進來使用,其實對於上圖所需要的功能,一下子就可以解決了,
但在ActionScript 中可能就需做些簡單的變化,下列我就直接介紹一些幾個在做這個功能需要的 Class。
1. URLLoder / URLStream:這二個是主要做對於 HTTP 協定下跟 Server 端呼叫與互動的主要 Class,不過對於連結檔案的時候,需要透過自行加上
                             上一個事件,來處理連結成功與連結失敗情形自已需要去處理的事件,這個方式與 HTTPServices 很類似。因此,通常我們會使用到
                             二個 Function (一個是做為 URLLoader 宣告與 Load的動作,一個是處理 Load成功後要做的事情) 來完成一次連結或下載的動作。
2. File / FileStream:這二個是放在 flash.filesystem 下的二個 Class,File 在 ActionScript中,主要是代表一個 Point的功能,用來指出我們所需要的檔案
                            所在的位置;另外 FileStream這個就不用說了,主要是用來處理檔案的寫入與讀取的串流。
【所遭遇到的問題】
上次洋洋灑灑說了那麼一大堆,好像都沒有把問題提一下,其實我只是希望大家多少能看懂我自己在寫些什麼東西而已,那麼接下來我就直接說明
所遇到的問題,以下是我撰寫程式的部分:
private function loadImages():void
{
    for (var intX:int=0;intX<imgArray.length;intX++)
    {
        if (imgArray[intX].toString()!="")
        {    
            fileTempPath=imgArray[intX]; //指定要下載的檔案位置與檔名             
            var urlLoader:Loader=new Loader();
            urlLoader.addEventListener(Event.COMPLETE, writeImage);
            urlLoader.load(new URLRequest(serverPath+imgArray[intX]));    
        }
    }
}
當我這樣寫的時候,將會遇到一個問題:因為urlLoader在下載第一個檔案的時候,它會觸發 Event.COMPLETE的事件,但是因為 for loop還沒有結束
因此,將會變成如果我今天XML中有二個檔案名稱,為 muisc1.mp3與 music2.mp3的話,那最後下載的結果只會有一個檔案,是 music2.mp3,很怪吧。
後來根據我的一些詢問其他高手的結果,最有可能的原因是在於,我今天的寫法是它變成 function式的觸發方式,會變成一個function呼叫完,又重
新被呼叫一次,造成function被覆蓋上去,因此,最後的結果只會剩下最後一個檔案的內容,這應該是程序式寫法與物件式寫法上的一些問題吧。
【解決方式】
後來我想到的解決方式,是將我要進行下載與寫入檔案的部分,透過獨立成一個 ActionScript的 Class的方式來解決,因為當我獨立成一個 Class時,
那代表我今天要下載與寫入的動作,是由我 instance出來的這個 object要去做的事情,而不是 function之間的呼叫問題。以下是我 Class的定義部分:
package components
{
    import flash.filesystem.*;
    import flash.net.*;
    import flash.utils.ByteArray;
    
    public class customDownloadlist
    {
        [Bindable]
        private var strFileName:String="";
        
        public function customDownloadlist()
        {
        }

        public function download(request:URLRequest, defaultFileName:String=null):void
        {
            var urlStream:URLStream=new URLStream();
            urlStream.addEventListener(Event.COMPLETE, writeFile);
            urlStream.load(request);
            strFileName=defaultFileName;
        }
        private function writeFile(evt:Event):void
        {
            var fileBytes:ByteArray=new ByteArray();
            evt.target.readBytes(fileBytes);
            var soundfileStream:FileStream=new FileStream();
            var soundfile:File=File.applicationStorageDirectory.resolvePath(strFileName);
            soundfileStream.open(soundfile, FileMode.WRITE);
            soundfileStream.writeBytes(fileBytes);
            soundfileStream.close();
        }
    }
}
那在 Flex程式中呢,只需要加上 instance這個class 就可以解決嘍。
var objdownloadfiles:customDownloadlist=new customDownloadlist(); 
objdownloadfiles.download(new URLRequest(strPath),objXML.Filelist.File[intX].@url); 
//objXML.Filelist.File[intX].@url是從xml中取出的檔名

Pou's 的標籤:Adobe Flex,ActionScript,.NET,URLLoader,URLStream,File,FileStream,XML