Delphi用ICS控件进行断点续传
原帖地址:http://www.lonetear.net/bbs/read.asp?id=36143
原帖地址2(傻猫):http://www.samool.com/archives/41252/
用HTTPCLI和NMHTTP都可以实现断点续传,原理都一样,但是由于HTTPCLI支持带用户名和密码的HTTP代理,NMHTTP不支持,HTTPCLI还支持SOCK4、SOCK5代理,因此我选用HTTPCLI来实现。
主要是通过HTTPCLI的ContentRangeBegin和ContentRangeEnd属性来控制,ContentRangeBegin是指从哪个字节开始下载,ContentRangeEnd是指下载到哪个字节为止,如果留空则表示下载到文件结束。例如
httpcli1.ContentRangeBegin:='100'; //从100字节的位置开始下载
httpcli1.ContentRangeEnd:='200'; //下载到200字节的地方停止
httpcli1.ContentRangeBegin:='100'; //从100字节的位置开始下载
httpcli1.ContentRangeEnd:=''; //下载到文件结束
看下面的例子
var
f:TSearchRec;
FindFirst(fname,faAnyFile,f);
httpcli1.ContentRangeBegin:=inttostr(f.Size);
httpcli1.ContentRangeEnd:='';
Httpcli1.RcvdStream:=TFileStream.Create(fname,fmOpenReadWrite);
httpcli1.url:='xxxxxxx';//一个URL地址
httpcli1.Get;
Httpcli1.RcvdStream.Destroy;
Httpcli1.RcvdStream:= nil;
很奇怪的是,用了上面的语句,续传是续传了,但是续传的内容总是把先前的内容覆盖了,开始以为是Httpcli1.RcvdStream:=TFileStream.Create(fname,fmOpenReadWrite);中fmOpenReadWrite参数的问题,换完了所有的参数问题依旧,后来在网上看到一些相关的C++例程,受到一点启发,其实续传的代码没有错,错在对文件的处理上,当TFileStream.Create之后,文件指针的位置默认是文件开头,应当把文件指针指向结尾,修正后的代码如下:
var
fs:TFileStream;
fs:=TFileStream.Create(fname,fmOpenReadWrite);
fs.Position:=fs.size; //将文件指针移到文件的结尾,用SEEK也可实现
httpcli1.ContentRangeBegin:=fs.Size;
httpcli1.ContentRangeEnd:='';
Httpcli1.RcvdStream:=fs;
httpcli1.url:='xxxxxxx';//一个URL地址
httpcli1.Get;
fs.free;
用以上的代码完全可以实现断点续传,目前还有一个问题没有解决,如果下载的URL是一个动态脚本的话,例如ASP文件,在ASP文件中如果发生了
response.redirect使URL动态改变,断点续传就无法实现,在HTTPCLI的locationchange事件中showmessage(httpcli1.url);发现虽然ASP文件中用REDIRECT改变了URL,但是HTTPCLI的URL并没有更新,估计这是无法续传的原因。
欢迎大家继续讨论。 ------------------------------------------------
现在的下载软件一般都是多线程,多资源的下载模式,本文用ICS中的TMultipartHttpDownloader组件实现多线程,单资源的分块下载模式,鲁大师的升级就是这样的原理,可以参考.
先看组件的几个事件:
HTTPRequestDone(Sender: TObject; ErrorCode: Integer; const Reason: string);
下载完成事件,在这里可以释放下载的文件流
FMultiPartHTTP.FileStream.Free;
FMultiPartHTTP.FileStream := nil;
HTTPShowStats(Sender: TObject);
下载显示状态信息事件
'已下载(MB):' + Format('%2f',[FMultiPartHTTP.TotalCount / 1024 / 1024]) +
' 完成:' + Format('%3.0f', [FMultiPartHTTP.PercentDone])+'%' +
' 速度(KB/秒):' + Format('%6.2f', [FMultiPartHTTP.CurSpeed]) +
' 耗时:' + FormatDateTime('hh:nn:ss', FMultiPartHTTP.ElapsedTime);
下面2个事件和进度条有关,ICS自带了个下载进度条
HTTPProgressAddSegment(Sender: TObject; StartOffset, ASpan, InitPos: Int64);
ASpan分段大小,InitPos分段开始大小, StartOffset,分段开始大小
HTTPProgressSetPosition(Sender: TObject;Index: Integer; Position: Int64);
Index第几个分段 Position 分段已下载的大小
下面是用法,非常简单:
FMultiPartHTTP.URL:=下载文件地址;
FMultiPartHTTP.PartCount:=分块个数;
FMultiPartHTTP.FileStream:=TFileStream.Create('下载本地文件名',fmCreate);
FMultiPartHTTP.Start;
注意:PartCount要大于1,这个组件支持断网断点下载,如果要控制下载的线程数量需要改ICS的源代码
来源:oschina
链接:https://my.oschina.net/u/582827/blog/275919