对于flash,断点续传这个东东,有了AIR,才真正发挥了它的用武之地。具体怎么实现的呢,请看瑞研社区的文章,点击进入瑞研社区。
在这里,稍微改了一点点。是AIR在ios上的断点续传。差别似乎不大。但是有一点,需要注意。通过File,我们很容易指向文档目录,临时存贮目录等。但是,我们一般都不是只放在指向的根目录。而是有它的内层目录。比如,指向文档目录下,temp目录下,怎么写呢。
var fileName:String = "crazy.swf"; file = File.documentsDirectory; file = file.resolvePath(file.nativePath + "/temp/" + fileName);
这里要注意File的属性nativePath和url。
要说的第二点,增加了对文件加载总进度的侦听。这一点,有个处理。如果文件很小,或文件已经加载完了。再点击加载的情况。
不说了,贴出源代码。然后洗澡澡,睡觉觉了。对于ios下,文件的操作方面还待研究,不比在win下。
package { import com.vini123.utils.Button; import flash.display.Sprite; import flash.display.StageAlign; import flash.display.StageScaleMode; import flash.events.Event; import flash.events.MouseEvent; import flash.events.ProgressEvent; import flash.filesystem.File; import flash.filesystem.FileMode; import flash.filesystem.FileStream; import flash.net.URLLoader; import flash.net.URLLoaderDataFormat; import flash.net.URLRequest; import flash.net.URLRequestHeader; import flash.utils.ByteArray; public class IosBreakPointsLoad extends Sprite { private var horizontalMc:HorizontalMc; private var verticalMc:VerticalMc; private var btnCnNameArr:Array = ["加载","暂停","恢复","打开"]; private var btnEngNameArr:Array = ["loadBtn","pauseBtn","resumeBtn","openBtn"]; private var btnArr:Vector.<Button> = new Vector.<Button>(); [Bindable] private var progress:Number = 0; private var contentLength:int = 0; private var file:File; private var startPoint:int = 0; private var endPoint:int = 0; private var rangeLoader:URLLoader; private var range:int = 50000; [Bindable] private var downloadStatus:Boolean = false; private var urlArr:Array= ["http://av.adobe.com/devnet/flex/fiaw/fiaw_v1_01.flv","http://vini123.sinaapp.com/index.swf"]; public function IosBreakPointsLoad() { super(); stage.align = StageAlign.TOP_LEFT; stage.scaleMode = StageScaleMode.NO_SCALE; Init(); } private function Init():void { verticalMc = new VerticalMc(); addChild(verticalMc); verticalMc.visible = false; horizontalMc = new HorizontalMc(); addChild(horizontalMc); horizontalMc.width = 960 horizontalMc.height = 610; var len:int = btnCnNameArr.length; for(var i:int =0 ; i< len ; i++) { var btn:Button = new Button(btnCnNameArr[i]); btn.buttonMode = true; btn.name = btnEngNameArr[i]; btn.addEventListener(MouseEvent.CLICK,clickHandler); btnArr.push(btn); if(i ==0) { btn.x = 10; } else { btn.x = 10 + i * (btnArr[i-1].width +10) } btn.y = 10; addChild(btn); } var dotSplitLength:uint = urlArr[0].split("/").length;//这两行代码是为了获取下载文件的名称 var fileName:String = urlArr[0].split("/")[dotSplitLength-1]; file = File.documentsDirectory; file = file.resolvePath(file.nativePath + "/temp/" +fileName); } private function clickHandler(e:MouseEvent):void { var tarName:String = e.currentTarget.name; switch(tarName) { case "loadBtn": doDownload(); break; case "pauseBtn": pause(); break; case "resumeBtn": downloadByRange(); break; case "openBtn": open(); break; } } /** *开始下载 */ private function doDownload():void { //先发送一个下载请求,可以得到文件的真实尺寸 var getContentLengthRequest:URLRequest = new URLRequest(urlArr[0]); var getContentLengthLoader:URLLoader = new URLLoader(); getContentLengthLoader.addEventListener(ProgressEvent.PROGRESS ,function(e:ProgressEvent):void { contentLength = getContentLengthLoader.bytesTotal;//得到文件的真实尺寸 getContentLengthLoader.close();//停止下载 downloadByRange();//按照断点续传的方式下载 }); getContentLengthLoader.load(getContentLengthRequest); } /** *继续下载 */ private function downloadByRange():void { //按照断点续传的方式下载 downloadStatus = true; var fileStr:FileStream = new FileStream(); if(file.exists) { //如果文件是存在的,就说明下载过,需要计算从哪个点开始下载 fileStr.open(file, FileMode.READ); startPoint = fileStr.bytesAvailable;//计算从哪个点开始下载 fileStr.close();//关闭文件流 } trace("start:"+startPoint,contentLength); if(startPoint == contentLength) { trace("此刻已经加载完毕!"); return; } if(startPoint+range > contentLength) { //确定下载的区间范围,比如0-10000 endPoint = contentLength; } else { endPoint = startPoint+range; } var rangeRequest:URLRequest = new URLRequest(urlArr[0]); var header:URLRequestHeader = new URLRequestHeader("Range", "bytes="+startPoint+"-"+endPoint);//注意这里很关键,我们在请求的Header里包含对Range的描述,这样服务器会返回文件的某个部分 rangeRequest.requestHeaders.push(header);//将头信息添加到请求里 rangeLoader = new URLLoader(); rangeLoader.dataFormat = URLLoaderDataFormat.BINARY;//设置数据类型为字节 rangeLoader.addEventListener(ProgressEvent.PROGRESS,loadProgressHandler) rangeLoader.addEventListener(Event.COMPLETE ,function(e:Event):void { var currentData:ByteArray = rangeLoader.data;//得到下载的数据 fileStr = new FileStream(); fileStr.open(file, FileMode.UPDATE); fileStr.position = fileStr.bytesAvailable;//将指针指向文件尾 fileStr.writeBytes(currentData, 0, currentData.length);//在文件中写入新下载的数据 fileStr.close();//关闭文件流 progress = endPoint/contentLength * 100;//计算下载进程 if(progress < 100) { downloadByRange();//如果下载没有完成,则执行下一个断点下载,直到下载完毕整个文件 } else { rangeLoader.removeEventListener(Event.COMPLETE,arguments.callee); //删除侦听 rangeLoader.removeEventListener(ProgressEvent.PROGRESS,loadProgressHandler) trace("加载完毕!"); } }); rangeLoader.load(rangeRequest);//发起请求 } private function loadProgressHandler(e:ProgressEvent):void { var loadProgressNum:Number; if(range > contentLength) { loadProgressNum = Accuracy(e.bytesLoaded/e.bytesTotal , 2) } else { loadProgressNum = Accuracy((endPoint/contentLength + e.bytesLoaded/e.bytesTotal * range/contentLength),2) } trace(loadProgressNum) } private function Accuracy(num:Number,accNum:int=1):Number { var tempNum:Number = Math.round(num * Math.pow(10,accNum))/Math.pow(10,accNum); return tempNum; } /** *暂停 */ private function pause():void { downloadStatus = false; rangeLoader.close(); } /** *打开 */ private function open():void { file.openWithDefaultApplication(); } } }
package com.vini123.utils { import flash.display.Sprite; import flash.events.MouseEvent; import flash.text.TextField; import flash.text.TextFieldAutoSize; import flash.text.TextFormat; public class Button extends Sprite { private var _txtFormat:TextFormat; private var _txt:TextField private var _bottom:Sprite; private var _gap:int =15; public function Button(label:String):void { _txtFormat = new TextFormat(); _txtFormat.size = 30; _txtFormat.color = 0xADD0FC; _txt = new TextField(); _txt.text = label; _txt.autoSize = TextFieldAutoSize.LEFT; _txt.setTextFormat(_txtFormat); _txt.mouseEnabled = false; addChild(_txt); _bottom = new Sprite(); _bottom.graphics.lineStyle(1.0,0x2D72B5); _bottom.graphics.beginFill(0x0099ff,1); _bottom.graphics.drawRoundRect(0,0,_txt.textWidth + _gap *2,_txt.textHeight + _gap,5,5); _bottom.graphics.endFill(); addChildAt(_bottom,0); _txt.x = _gap; _txt.y = _gap * 0.5 -1; this.addEventListener(MouseEvent.ROLL_OVER,overHandler); this.addEventListener(MouseEvent.ROLL_OUT,outHandler); } private function overHandler(e:MouseEvent):void { _txt.alpha = 0.65; } private function outHandler(e:MouseEvent):void { _txt.alpha = 1; } public function dispose():void { _bottom.graphics.clear(); this.removeEventListener(MouseEvent.ROLL_OVER,overHandler); this.removeEventListener(MouseEvent.ROLL_OUT,outHandler); if(this.parent) { this.parent.removeChild(this); } } } }