摘要:Flex Multi-URLLoader with For Loop
最近開始研究關於 Adobe Flex 與 ActionScript 3,對於它一些相關 Class 的組成架構,到最近才有所突破,不過或多或少有遇到一些小問題,
這次主要是說明關於 URLLoader 或 URLStream 對於一個以上的檔案要做下載的同時會遇到的問題,其情境的說明我用下列小圖簡單說明一下:
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