11RIA 闪客社区 - 最赞 Animate Flash 论坛

搜索
查看: 1946|回复: 2
上一主题 下一主题

[网络 & 通信] HTTP 断点续传原理,及 Flex AS AIR 实现技术

[复制链接] TA的其它主题
发表于 2019-3-11 10:13:03 | 显示全部楼层 |阅读模式

【游客模式】——注册会员,加入11RIA 闪客社区吧!一起见证Flash的再次辉煌……

您需要 登录 才可以下载或查看,没有帐号?立即注册

x
转载:QQ群
地址:未知
作者:未知


一、Http断点续传原理
现在基本上任何一个下载工具都是支持断点续传的,抛开P2P的成分不谈,我们单说通过HTTP服务器是如何实现断点续传的。关键在于你向HTTP服务器发起文件请求的时候,是否明确的告知,要下载文件的哪个区域,我们都知道HTTP请求是有一个Header的,实际上里面有个属性是定义下载的区域的,这个属性就是Range,它接收的值是一个区间范围,比如:Range:bytes=0-10000

这样我们就可以按照一定的规则,将一个大文件拆分为若干很小的部分,然后分批次的下载,每个小块下载完成之后,都合并到文件中,这样即时中间中断了下载,我们重新开始下载的时候,也可以通过文件的字节长度来判断下载的起始点,然后重启断点续传的过程,直到最后完成下载过程。

1、 下面是非断点续传的Http剖析
假设我们通过浏览器去下载一个
称为hello.zip的文件。那么浏览器发出的请求信息如下:
GET /hello.zip HTTP/1.1
Accept: image/gif, image/x-xbitmap, image/jpeg, image/pjpeg, application/vnd.ms-excel, application/msword, application/vnd.ms-powerpoint
Accept-Language: zh-cn
Accept-Encoding: gzip, deflate
User-Agent: Mozilla/4.0 (compatible; MSIE 5.01; Windows NT 5.0)
Connection: Keep-Alive

服务器收到请求后,按要求寻找请求的文件,提取文件的信息,然后返回给浏览器,返回信息如下:
200
Content-Length=106786028
Accept-Ranges=bytes
Date=Mon, 30 Apr 2009 12:56:11 GMT
ETag=W/"02ca57e173c12:95b"
Content-Type=application/octet-stream
Last-Modified=Mon, 30 Apr 2009 12:56:11 GMT

2、下面是断点续传的http剖析
如果自己编的一个客户端程序来传递请求信息给Web服务器,要求从1000070字节开始。
GET /hello.zip HTTP/1.0
User-Agent: NetFox
RANGE: bytes=1000070-
Accept: text/html, image/gif, image/jpeg, *; q=.2, */*; q=.2

仔细看一下就会发现多了一行RANGE: bytes=1000070-,这一行的意思就是告诉服务器hello.zip这个文件从1000070字节开始传,前面的字节不用传了。
服务器收到这个请求以后,返回的信息如下:
206
Content-Length=106786028
Content-Range=bytes 1000070-106786027/106786028
Date=Mon, 30 Apr 2009 12:55:20 GMT
ETag=W/"02ca57e173c12:95b"
Content-Type=application/octet-stream
Last-Modified=Mon, 30 Apr 2009 12:55:20 GMT

和前面服务器返回的信息比较一下,就会发现增加了Content-Range一行,且返回的代码也改为206了,而不再是200了。
以上就是HTTP断点续传的原理,具体通过什么技术实现,比如Java、C++、Flex等,都可以实现。


二、Flex实现的文件下载断点续传
下面是基于AS3+Flash Player+AIR,制作一个断点续传的小程序,大概实现思路如下:
1、首先对文件发起请求,得到文件的尺寸(字节长度),但并不下载
2、然后将文件划分为若干区域,对第一个区域的内容发起请求(通过指定HTTP头的Range)
3、第一个区域的内容很快下载完成,使用File保存到本地文件
4、移动指针,对第二个区域的内容发起请求,下载完毕后与文件合并
5、以此类推,直到下载完成整个文件
以下是实现代码:
[Actionscript3] 纯文本查看 复制代码
<?xml version="1.0" encoding="utf-8"?>
<mx:WindowedApplication xmlns:mx="http://www.adobe.com/2006/mxml" layout="absolute" title="梦想下载" >
    <mx:Script>
        <![CDATA[
            import flash.net.URLLoader;
            import flash.net.URLStream;
            import flash.net.URLRequest;
            import flash.utils.ByteArray;
            import mx.controls.Alert;
            private var contentLength:int = 0;
            private var file:File;
            private var startPoint:int = 0;
            private var endPoint:int = 0;
            private var rangeStream:URLStream;
            private var isInit:Boolean = false;
            private var range:int = 1024000; //每次下载的字节数,
            private  var currentData:ByteArray;
            private var progress:Number = 0;
            private function init():void {
                var dotSplitLength:uint = videoURL.text.split("/").length;//这两行代码是为了获取下载文件的名称
                var fileName:String = videoURL.text.split("/")[dotSplitLength-1];
                file = new File("C:/DownLoadTemp/"+fileName);//创建一个和下载文件名称一致的文件,保存在D盘temp目录下
                isInit = true;
            }
            private function doDownload():void {//先发送一个下载请求,可以得到文件的真实尺寸
                var getContentLengthRequest:URLRequest = new URLRequest(videoURL.text);
                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 {//按照断点续传的方式下载
            	if(!isInit)
            		init();
                var fileStr:FileStream = new FileStream();
                if(file.exists) {//如果文件是存在的,就说明下载过,需要计算从哪个点开始下载
                    fileStr.open(file, FileMode.READ);
                    startPoint = fileStr.bytesAvailable;//计算从哪个点开始下载
                    fileStr.close();//关闭文件流
                }
                endPoint = startPoint+range>contentLength?contentLength:startPoint+range;
        		if(startPoint==contentLength)
        		{
        			Alert.show("您已经完成了下载");
        			return;
        		}
                var rangeRequest:URLRequest = new URLRequest(videoURL.text);
                var header:URLRequestHeader = new URLRequestHeader("Range", "bytes="+startPoint+"-"+endPoint);//注意这里很关键,我们在请求的Header里包含对Range的描述,这样服务器会返回文件的某个部分
                rangeRequest.requestHeaders.push(header);//将头信息添加到请求里
                rangeStream = new URLStream();
                rangeStream.addEventListener(Event.COMPLETE ,function(e:Event):void {
					var bytesLength:int = rangeStream.bytesAvailable;
                    currentData = new ByteArray();
                    rangeStream.readBytes(currentData, 0, bytesLength); //得到下载的数据
                    fileStr = new FileStream();
                    fileStr.open(file, FileMode.UPDATE);
                    fileStr.position = fileStr.bytesAvailable;//将指针指向文件尾
                    fileStr.writeBytes(currentData, 0, currentData.length);//在文件中写入新下载的数据
                    fileStr.close();//关闭文件流
                    progress = endPoint/contentLength * 100;//计算下载进程
                    bar.setProgress(progress,100);
                 	bar.label= "Progress" + " " + progress + "%";
                    if(endPoint < contentLength) {
                        downloadByRange();//如果下载没有完成,则执行下一个断点下载,直到下载完毕整个文件
                    }
                });
                rangeStream.load(rangeRequest);//发起请求
            }
            private function pause():void {//暂停下载
                if(rangeStream!=null&&rangeStream.connected)
                	rangeStream.close();
            }
        ]]>
    </mx:Script>
    <mx:Canvas width="494" height="284" horizontalCenter="0" verticalCenter="0">
        <mx:Label x="21" y="87"  text="下载地址" width="53" fontSize="12" />
        <mx:TextInput x="82" y="87" width="399" id="videoURL" text="http://192.168.12.131:8080/FlexChatServer/AContreCourant.avi"/>
        <mx:Button x="160" y="141" label="下载"  id="btDownload" fontSize="12" click="doDownload();btDownload.enabled=false;btPause.enabled=true;btContinue.enabled=false"/>
        <mx:Button x="221" y="141" label="暂停" id="btPause" fontSize="12" enabled="false" click="pause();btPause.enabled=false;btContinue.enabled=true"/>
        <mx:Button x="281" y="141" label="继续" id="btContinue" fontSize="12" enabled="false" click="downloadByRange();btPause.enabled=true;btContinue.enabled=false"/>
        <mx:ProgressBar x="82" y="194" width="399" id="bar" labelPlacement="bottom" themeColor="#EE1122" minimum="0" visible="true" maximum="100"
             color="0x323232"    label="Progress 0%" direction="right" mode="manual" />
    </mx:Canvas>
</mx:WindowedApplication>


运行效果:
QQ图片20190311101601.png

评分

参与人数 1银子 +10 贡献 +1 收起 理由
TKCB + 10 + 1

查看全部评分

发表于 2019-3-11 10:14:39 | 显示全部楼层
【11RIA 闪客社区,评分公示】:
是否有价值:一般(银子 +10  贡献 +1)
是否原创:否
是否翻译:否
如对自己的评分有疑问,则咨询版主、管理员等。
回复

使用道具 举报

发表于 2019-3-12 06:25:20 | 显示全部楼层
感谢分享!!
回复

使用道具 举报

您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

关闭

站长推荐 上一条 /1 下一条

感谢所有支持论坛的朋友:下面展示最新的5位赞助和充值的朋友……更多赞助和充值朋友的信息,请查看:永远的感谢名单

SGlW(66139)、 anghuo(841)、 whdsyes(255)、 longxia(60904)、 囫囵吞澡(58054)

下面展示总排行榜的前3名(T1-T3)和今年排行榜的前3名的朋友(C1-C3)……更多信息,请查看:总排行榜今年排行榜

T1. fhqu1462(969)、 T2. lwlpluto(14232)、 T3. 1367926921(962)  |  C1. anghuo(147)、 C2. fdisker(27945)、 C3. 囫囵吞澡(58054)



快速回复 返回顶部 返回列表