http断点续传的单元

{******************************************************************************
    文件名称: uWnDownLoadHelper.pas
    文件功能: 断点续传下载线程单元
    作者    : enli
--------------------------------------------------------------------------------}
unit  uWnDownLoadHelper;

interface

uses
  IdHTTP, IdAuthentication, IdHeaderList, IniFiles, md5,
  SysUtils, IdAuthenticationSSPI, IdAuthenticationDigest, Classes, IdException,
  IdSocks, IdIOHandlerSocket, DateUtils, IdComponent, Forms,ucchttpClient;

const
  S_TMP_POSTFIX 
=   ' .tmp ' ;
  S_INI_POSTFIX 
=   ' .sni ' ;

type
  TWnDownloadProgress 
=   procedure (APosition,ACount: Int64)  of   object ;

  
//  代理设置结构
  TWnProxySetting 
=   packed   record
    FIsProxyEnabled: Boolean;
    FSocksVersion: TSocksVersion;
    FProxyHost: 
string ;
    FProxyPort: Word;
    FAuthUserName: 
string ;
    FAuthPassword: 
string ;
    FAuthDomain:
string ;
  
end ;
  PWnProxySetting 
=  ^TWnProxySetting;

  TWnDownLoadThread 
=   class (TThread)
  
private
    FHttp: TCCHTTPClient;
    FProxy: TWnProxySetting;
    FTarget: 
string ;
    FSaveFile: 
string ;
    FTempFile: 
string ;
    FProgress: TWnDownloadProgress;
    FCurrentFileSize,FFileSize : Int64;
    FSaveLocation: 
string ;
    FOnLog: TDolog;
    FWarningMsg: 
string ;
    FReLoad: Boolean;
    
procedure  SetProxy( const  Value: PWnProxySetting);
    
function  GetProxy :PWnProxySetting;
    
procedure  SetHttpProxy;
    
procedure  SetTarget( const  Value:  string );
    
procedure  SetProgress( const  Value: TWnDownloadProgress);
    
procedure  DoBeginWork(Sender: TObject; const  APos,ACount: Int64);
    
procedure  DoWork(Sender: TObject; const  AWork:Int64);
    
procedure  DoEndWork(Sender: TObject);
    
procedure  DoUpdateUI;
    
procedure  SetSaveLocation( const  Value:  string );
    
procedure  SaveIniFile;
    
procedure  DelIniFile;
    
procedure  DoLog( const  AMsg: string );
    
procedure  DoSycLog;
    
function  GetTempFile: string ;
    
procedure  SetOnLog( const  Value: TDolog);
    
procedure  SetReLoad( const  Value: Boolean);
  
public
    
procedure  Execute;  override ;
    
constructor  Create;
    
destructor  Destroy;  override ;
    
class   procedure  chunkedConvertToFile( const  ASource,ADestination: string );
    
property  PProxy:PWnProxySetting  read  GetProxy  write  SetProxy;
    
property  Target: string   read  FTarget  write  SetTarget;
    
property  SaveLocation : string   read  FSaveLocation  write  SetSaveLocation;
    
property  Progress:TWnDownloadProgress  read  FProgress  write  SetProgress;
    
property  ReLoad:Boolean  read  FReLoad  write  SetReLoad;
    
property  OnLog: TDolog  read  FOnLog  write  SetOnLog;
  
end ;

  
procedure  DownLoadFile( const  AUrl,ASaveFile: string ;AProxy:PWnProxySetting;AProgress:TWnDownloadProgress;ALog:TDolog;AReLoad:Boolean);

implementation

procedure  DownLoadFile( const  AUrl,ASaveFile: string ;AProxy:PWnProxySetting;AProgress:TWnDownloadProgress;ALog:TDolog;AReLoad:Boolean);
var
  LThread: TWnDownLoadThread;
begin
  LThread :
=  TWnDownLoadThread.Create;
  LThread.ReLoad :
=  AReLoad;
  LThread.Target :
=  AUrl;
  LThread.SaveLocation :
=  ASaveFile;
  LThread.PProxy :
=  AProxy;
  LThread.Progress :
= AProgress;
  LThread.OnLog :
=  ALog;
  LThread.Resume;
end ;

{  TWnDownLoadThread  }

class   procedure  TWnDownLoadThread.chunkedConvertToFile( const  ASource,
  ADestination: 
string );
var
  LSStream,LDStream: TFileStream;
  LBuff: Byte;
  LFlag: Boolean;
  LTemp : 
string ;
  I,LCount : Integer;
begin
  
if   not  FileExists(ASource)  then  Exit;
  
if  FileExists(ADestination)  then  Exit;
  LSStream :
=  TFileStream.Create(ASource,fmOpenRead    );
  LDStream :
=  TFileStream.Create(ADestination,fmCreate);
  
try
    LSStream.Seek(
0 , 0 );
    LFlag :
=  True;
    I :
=   0 ;
    
while  LFlag  do
    
begin
      LSStream.Read(LBuff,SizeOf(Byte));
      Inc(I);
      
if  (LBuff  =  $0A)  and  (I > 2 and  (LTemp[I - 1 =  #$0D)  then   begin
        LCount :
=  StrToIntDef( ' $ ' + trim(LTemp), 1 );
        
if  LCount  =   1   then
        
begin
          LCount :
=   0 ;
          Break;
          
// raise  异常
        
end ;
        
if  LCount  =   0   then
          LFlag :
=  False
        
else
        
begin
          LDStream.CopyFrom(LSStream,LCount);
          I :
=   0 ;
          LTemp :
=   '' ;
        
end ;
      
end
      
else
        LTemp :
=  LTemp  +  Char(LBuff);
    
end ;

  
finally
    FreeAndNil(LSStream);
    FreeAndNil(LDStream);
  
end ;

end ;

constructor  TWnDownLoadThread.Create;
begin
  
inherited  Create(True);
  FreeOnTerminate :
=  True;
  FTarget :
=   '' ;
  FSaveFile :
=   '' ;
  
// New(FProxy);
end ;

procedure  TWnDownLoadThread.DelIniFile;
begin
  DeleteFile(FSaveLocation 
+  FTempFile + S_INI_POSTFIX);
end ;

destructor  TWnDownLoadThread.Destroy;
begin
  
// Dispose(FProxy);
  
inherited ;
end ;

procedure  TWnDownLoadThread.DoBeginWork(Sender: TObject;
  
const  APos,ACount: Int64);
begin
  FFileSize :
=  ACount;
  FCurrentFileSize :
=  APos ;
  SaveIniFile;
  Synchronize(DoUpdateUI);
end ;

procedure  TWnDownLoadThread.DoEndWork(Sender: TObject);
begin
  FCurrentFileSize :
=  FFileSize;
  Synchronize(DoUpdateUI);
end ;

procedure  TWnDownLoadThread.DoLog( const  AMsg:  string );
begin
  
if  Assigned(FOnlog)  then
  
begin
    
/// DoDownLoadLog(AMsg);
    FWarningMsg:
=  AMsg;
    Synchronize(DoSycLog);
  
end ;
end ;

procedure  TWnDownLoadThread.DoSycLog;
begin
  FOnlog(FWarningMsg);
end ;

procedure  TWnDownLoadThread.DoUpdateUI;
begin
  
if  Assigned(FProgress)  then
    FProgress(FCurrentFileSize,FFileSize);
end ;

procedure  TWnDownLoadThread.DoWork(Sender: TObject;  const  AWork: Int64);
begin
  FCurrentFileSize :
=  FCurrentFileSize +  AWork;
  Synchronize(DoUpdateUI);
end ;

procedure  TWnDownLoadThread.Execute;
var
  LDoc,
  LHost,
  LPath,
  LProto,
  LPort,
  LBookmark: 
string ;
begin
  
if  Length(FTarget)  =   0   then  Exit;
  
if  Length(FSaveLocation)  =   0   then  Exit;
  FHttp :
=  TCCHTTPClient.Create( nil );
  
try
    FHttp.IOHandler :
=  TIdIOHandlerSocket.Create(FHttp);
    FHttp.Socket.SocksInfo :
=  TIdSocksInfo.Create(FHttp);
    FHttp.ProtocolVersion :
=  uCCHTTPClient.pv1_ 1 ;    
    SetHttpProxy;
    FHttp.OnDownloadBegin :
=   DoBeginWork;
    FHttp.OnDownload :
=   DoWork;
    FHttp.OnDownloadEnd :
=  DoEndWork;
    FHttp.OnLog :
=  DoLog;

    FHttp.ParseURI(FTarget, LProto, LHost, LPath, LDoc, LPort, LBookmark);
    FSaveFile :
=  LDoc;
    FTempFile :
=  GetTempFile + ' . ' + LDoc;
    
if  FReLoad  and  FileExists(FSaveLocation  +  FTempFile + S_TMP_POSTFIX)  then
      DeleteFile(FSaveLocation 
+  FTempFile + S_TMP_POSTFIX);
    DoLog(
' 下载开始请求 ' );
    
try
      FHttp.DownLoad(FTarget,FSaveLocation 
+  FTempFile + S_TMP_POSTFIX);
    
except
      on E:Exception 
do
        DoLog(e.Message);
    
end ;
    
if  FileExists(FSaveLocation  +  FTempFile + S_INI_POSTFIX)  then
    
begin

      
if  FileExists(FSaveLocation  +  LDoc)  then
        DeleteFile(FSaveLocation 
+  LDoc);
      
if  FHttp.Response.TransferEncoding  =   ' chunked '   then
      
begin
        chunkedConvertToFile(FSaveLocation 
+  FTempFile + S_TMP_POSTFIX,FSaveLocation  +  LDoc);
        DeleteFile(FSaveLocation 
+  FTempFile + S_TMP_POSTFIX);
      
end
      
else
        RenameFile(FSaveLocation 
+  FTempFile + S_TMP_POSTFIX,FSaveLocation  +  LDoc);
      DelIniFile;
    
end
    
else
      DeleteFile(FSaveLocation 
+  FTempFile + S_TMP_POSTFIX);
  
finally
    FreeAndNil(FHttp);
    DoLog(
' 下载结束 ' );
  
end ;
end ;

function  TWnDownLoadThread.GetProxy: PWnProxySetting;
begin
  Result :
=  @FProxy
end ;

function  TWnDownLoadThread.GetTempFile:  string ;
var
  Ltemp: 
string ;
begin
  Ltemp :
=  MD5Print(MD5String(FTarget));
  
// Ltemp : =  copy(Ltemp,  2 , length(Ltemp)  -   2 );
  Result :
=  StringReplace(Ltemp, ' - ' , ' . ' ,[rfReplaceAll]    );
end ;

procedure  TWnDownLoadThread.SaveIniFile;
var
  LIni:TIniFile;
begin
  LIni :
=  TIniFile.Create(FSaveLocation  +  FTempFile + S_INI_POSTFIX);
  
try
    LIni.WriteString(
' Setup ' , ' URL ' ,FTarget);
    LIni.WriteString(
' Setup ' , ' SaveLocation ' ,FSaveLocation);
    LIni.WriteString(
' Setup ' , ' SaveFile ' ,FSaveFile);
    LIni.WriteString(
' Setup ' , ' TempFile ' ,FTempFile);
    LIni.WriteString(
' Setup ' , ' FileSize ' ,FloatToStr(FFileSize));
  
finally
    LIni.Free;
  
end ;

end ;

procedure  TWnDownLoadThread.SetHttpProxy;
begin
  
if   not  Assigned(FHttp)  then  Exit;
  
with  FProxy  do
  
if  FIsProxyEnabled  then
  
begin
    FHttp.Socket.SocksInfo.Version :
=  FSocksVersion;
    FHttp.Socket.SocksInfo.Host :
=  FProxyHost;
    FHttp.Socket.SocksInfo.Port :
=  FProxyPort;

    
if  FHttp.Socket.SocksInfo.Username  <>   ''   then
      FHttp.Socket.SocksInfo.Authentication :
=  saUsernamePassword
    
else
      FHttp.Socket.SocksInfo.Authentication :
=  saNoAuthentication;
    FHttp.AuthUsername :
=  FAuthUserName;
    FHttp.AuthPassword :
=  FAuthPassword;
    FHttp.AuthDomain   :
=  FAuthDomain;
    FHttp.ProxyHost    :
=  FProxyHost;
    FHttp.ProxyPort    :
=  FProxyPort;
  
end ;
end ;

procedure  TWnDownLoadThread.SetOnLog( const  Value: TDolog);
begin
  FOnLog :
=  Value;
end ;

procedure  TWnDownLoadThread.SetProgress( const  Value: TWnDownloadProgress);
begin
  FProgress :
=  Value;
end ;

procedure  TWnDownLoadThread.SetProxy( const  Value: PWnProxySetting);
begin
    
// New(FProxy);
    FProxy.FIsProxyEnabled :
= Value^.FIsProxyEnabled;
    FProxy.FSocksVersion :
=  Value^.FSocksVersion;
    FProxy.FProxyHost :
=  Value^.FProxyHost;
    FProxy.FProxyPort :
=  Value^.FProxyPort;
    FProxy.FAuthUserName :
=  Value^.FAuthUserName;
    FProxy.FAuthPassword :
=  Value^.FAuthPassword;
    FProxy.FAuthDomain   :
=  Value^.FAuthDomain;
    FProxy.FProxyHost   :
=  Value^.FProxyHost;
    FProxy.FProxyPort    :
=  Value^.FProxyPort;

end ;

procedure  TWnDownLoadThread.SetReLoad( const  Value: Boolean);
begin
  FReLoad :
=  Value;
end ;

procedure  TWnDownLoadThread.SetSaveLocation( const  Value:  string );
begin
  FSaveLocation :
=  Value;
  
if  FSaveLocation[Length(FSaveLocation)]  <>   ' \ '   then
    FSaveLocation :
=  FSaveLocation  + ' \ ' ;
end ;

procedure  TWnDownLoadThread.SetTarget( const  Value:  string );
begin
  
if  Length(Value)  =   0   then  Exit;
  
if  UpperCase(Copy(Value, 1 , 7 ))  <>   ' HTTP:// '   then  Exit;
  FTarget :
=  Value;
end ;

  end .
  备忘:IdDownLoad

转载于:https://www.cnblogs.com/enli/archive/2011/04/09/2010132.html

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值