利用IdHTTP进行多线程下载

摘自:http://blog.csdn.net/kuchong/archive/2006/03/02/613630.aspx

unit Unit1;
interface
uses
  Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
  Dialogs, ComCtrls, StdCtrls, IdComponent, IdTCPConnection, IdTCPClient,
  IdHTTP, IdBaseComponent, IdAntiFreezeBase, IdAntiFreeze,
  IdThreadComponent, IdFTP;
type
  TThread1 = class(TThread)
  private
    fCount, tstart, tlast: integer;
    tURL, tFile, temFileName: string;
    tResume: Boolean;
    tStream: TFileStream;
  protected
    procedure Execute; override;
  public
    constructor create1(aURL, aFile, fileName: string; bResume: Boolean; Count,
      start, last: integer);
    procedure DownLodeFile(); //下载文件
  end;
type
  TForm1 = class(TForm)
    IdAntiFreeze1: TIdAntiFreeze;
    IdHTTP1: TIdHTTP;
    Button1: TButton;
    ProgressBar1: TProgressBar;
    IdThreadComponent1: TIdThreadComponent;
    Label1: TLabel;
    Label2: TLabel;
    Button2: TButton;
    Button3: TButton;
    ListBox1: TListBox;
    Edit1: TEdit;
    Edit2: TEdit;
    Label3: TLabel;
    Label4: TLabel;
    procedure Button1Click(Sender: TObject);
    procedure IdHTTP1WorkBegin(Sender: TObject; AWorkMode: TWorkMode;
      const AWorkCountMax: Integer);
    procedure IdHTTP1Work(Sender: TObject; AWorkMode: TWorkMode;
      const AWorkCount: Integer);
    procedure Button2Click(Sender: TObject);
    procedure IdHTTP1Status(ASender: TObject; const AStatus: TIdStatus;
      const AStatusText: string);
    procedure Button3Click(Sender: TObject);
  private
  public
    nn, aFileSize, avg: integer;
    MyThread: array[1..10] of TThread;
    procedure GetThread();
    procedure AddFile();
    function GetURLFileName(aURL: string): string;
    function GetFileSize(aURL: string): integer;
  end;
var
  Form1: TForm1;
implementation
var
  AbortTransfer: Boolean;
  aURL, aFile: string;
  tcount: integer; //检查文件是否全部下载完毕
{$R *.dfm}
  //get FileName
function TForm1.GetURLFileName(aURL: string): string;
var
  i: integer;
  s: string;
begin //返回下载地址的文件名
  s := aURL;
  i := Pos('/', s);
  while i <> 0 do //去掉"/"前面的内容剩下的就是文件名了
  begin
    Delete(s, 1, i);
    i := Pos('/', s);
  end;
  Result := s;
end;
//get FileSize
function TForm1.GetFileSize(aURL: string): integer;
var
  FileSize: integer;
begin
  IdHTTP1.Head(aURL);
  FileSize := IdHTTP1.Response.ContentLength;
  IdHTTP1.Disconnect;
  Result := FileSize;
end;
//执行下载
procedure TForm1.Button1Click(Sender: TObject);
var
  j: integer;
begin
  tcount := 0;
  Showmessage('OK!主线程在执行,获得文件名并显示在Edit2中');
  aURL := Edit1.Text; //下载地址
  aFile := GetURLFileName(Edit1.Text); //得到文件名
  nn := StrToInt(Edit2.Text); //线程数
  j := 1;
  aFileSize := GetFileSize(aURL);
  avg := trunc(aFileSize / nn);
  begin
    try
      GetThread();
      while j <= nn do
      begin
        MyThread[j].Resume; //唤醒线程
        j := j + 1;
      end;
    except
      Showmessage('创建线程失败!');
      Exit;
    end;
  end;
end;
//开始下载前,将ProgressBar1的最大值设置为需要接收的数据大小.
procedure TForm1.IdHTTP1WorkBegin(Sender: TObject; AWorkMode: TWorkMode;
  const AWorkCountMax: Integer);
begin
  AbortTransfer := False;
  ProgressBar1.Max := AWorkCountMax;
  ProgressBar1.Min := 0;
  ProgressBar1.Position := 0;
end;
//接收数据的时候,进度将在ProgressBar1显示出来.
procedure TForm1.IdHTTP1Work(Sender: TObject; AWorkMode: TWorkMode;
  const AWorkCount: Integer);
begin
  if AbortTransfer then
  begin
    IdHTTP1.Disconnect; //中断下载
  end;
  ProgressBar1.Position := AWorkCount;
  //ProgressBar1.Position:=ProgressBar1.Position+AWorkCount; //*******显示速度极快
  Application.ProcessMessages;
  //***********************************这样使用不知道对不对
end;
//中断下载
procedure TForm1.Button2Click(Sender: TObject);
begin
  AbortTransfer := True;
  IdHTTP1.Disconnect;
end;
//状态显示
procedure TForm1.IdHTTP1Status(ASender: TObject; const AStatus: TIdStatus;
  const AStatusText: string);
begin
  ListBox1.ItemIndex := ListBox1.Items.Add(AStatusText);
end;
//退出程序
procedure TForm1.Button3Click(Sender: TObject);
begin
  application.Terminate;
end;
//循环产生线程
procedure TForm1.GetThread();
var
  i: integer;
  start: array[1..100] of integer;
  last: array[1..100] of integer;   //改用了数组,也可不用
  fileName: string;
begin
  i := 1;
  while i <= nn do
  begin
    start[i] := avg * (i - 1);
    last[i] := avg * i -1; //这里原先是last:=avg*i;
    if i = nn then
    begin
      last[i] := avg*i + aFileSize-avg*nn; //这里原先是aFileSize
    end;
    fileName := aFile + IntToStr(i);
    MyThread[i] := TThread1.create1(aURL, aFile, fileName, false, i, start[i],
      last[i]);
    i := i + 1;
  end;
end;
procedure TForm1.AddFile(); //合并文件
var
  mStream1, mStream2: TMemoryStream;
  i: integer;
begin
  i := 1;
  mStream1 := TMemoryStream.Create;
  mStream2 := TMemoryStream.Create;
  mStream1.loadfromfile('设备工程进度管理前期规划.doc' + '1');
  while i < nn do
  begin
    mStream2.loadfromfile('设备工程进度管理前期规划.doc' + IntToStr(i + 1));
    mStream1.seek(mStream1.size, soFromBeginning);
    mStream1.copyfrom(mStream2, mStream2.size);
    mStream2.clear;
    i := i + 1;
  end;
  mStream2.free;
  mStream1.SaveToFile('设备工程进度管理前期规划.doc');
  mStream1.free;
  //删除临时文件
  i:=1;
   while i <= nn do
  begin
    deletefile('设备工程进度管理前期规划.doc' + IntToStr(i));
    i := i + 1;
  end;
  Form1.ListBox1.ItemIndex := Form1.ListBox1.Items.Add('下在成功');
end;
//构造函数
constructor TThread1.create1(aURL, aFile, fileName: string; bResume: Boolean;
  Count, start, last: integer);
begin
  inherited create(true);
  FreeOnTerminate := true;
  tURL := aURL;
  tFile := aFile;
  fCount := Count;
  tResume := bResume;
  tstart := start;
  tlast := last;
  temFileName := fileName;
end;
//下载文件函数
procedure TThread1.DownLodeFile();
var
  temhttp: TIdHTTP;
begin
  temhttp := TIdHTTP.Create(nil);
  temhttp.onWorkBegin := Form1.IdHTTP1WorkBegin;
  temhttp.onwork := Form1.IdHTTP1work;
  temhttp.onStatus := Form1.IdHTTP1Status;
  Form1.IdAntiFreeze1.OnlyWhenIdle := False; //设置使程序有反应.
  if FileExists(temFileName) then //如果文件已经存在
    tStream := TFileStream.Create(temFileName, fmOpenWrite)
  else
    tStream := TFileStream.Create(temFileName, fmCreate);
  if tResume then //续传方式
  begin
    exit;
  end
  else //覆盖或新建方式
  begin
    temhttp.Request.ContentRangeStart := tstart;
    temhttp.Request.ContentRangeEnd := tlast;
  end;
  try
    temhttp.Get(tURL, tStream); //开始下载
    Form1.ListBox1.ItemIndex := Form1.ListBox1.Items.Add(temFileName +
      'download');
  finally
    //tStream.Free;
    freeandnil(tstream);
    temhttp.Disconnect;
  end;
end;
procedure TThread1.Execute;
begin
  if Form1.Edit1.Text <> '' then
    //synchronize(DownLodeFile)
    DownLodeFile
  else
    exit;
  inc(tcount);
  if tcount = Form1.nn then //当tcount=nn时代表全部下载成功
  begin
    //Showmessage('全部下载成功!');
    Form1.ListBox1.ItemIndex := Form1.ListBox1.Items.Add('正在合并删除临时文件');
    Form1.AddFile;
  end;
end;
end.

在 Delphi 中使用 IdFTP 和 IdHTTP 进行多线程下载并显示多个进度条的方法如下: 1. 使用 TThread 类创建一个新的线程,将 IdFTP 或 IdHTTP 放在其中。 2. 在新线程中使用 Synchronize 方法更新主线程中的进度条控件。 3. 在主线程中创建多个进度条控件,并将每个控件与一个下载任务相关联。 4. 在新线程中,使用 OnWork 事件来更新相关的进度条控件。 示例代码如下: ```delphi type TDownloadThread = class(TThread) private FUrl: string; FLocalPath: string; FProgressBar: TProgressBar; FIdFTP: TIdFTP; //或者是FIdHTTP: TIdHTTP; procedure DoUpdateProgress; protected procedure Execute; override; public constructor Create(const AUrl, ALocalPath: string; AProgressBar: TProgressBar); overload; end; constructor TDownloadThread.Create(const AUrl, ALocalPath: string; AProgressBar: TProgressBar); begin inherited Create(False); FUrl := AUrl; FLocalPath := ALocalPath; FProgressBar := AProgressBar; FreeOnTerminate := True; FIdFTP := TIdFTP.Create(nil); //或者是FIdHTTP := TIdHTTP.Create(nil); FIdFTP.OnWork := OnWork; end; procedure TDownloadThread.Execute; begin FIdFTP.Get(FUrl, FLocalPath); end; procedure TDownloadThread.DoUpdateProgress; begin FProgressBar.Position := FIdFTP.TransferProgress; end; procedure TForm1.Button1Click(Sender: TObject); var i: Integer; Thread: TDownloadThread; begin for i := 0 to 9 do begin ProgressBarList[i] := TProgressBar.Create(Self); ProgressBarList[i].Parent := Self; ProgressBarList[i].Top := i * 20; ProgressBarList[i].Left := 0; ProgressBarList[i].Width := 200; ProgressBarList[i].Max := 100; ProgressBarList[i].Visible := True; Thread := TDownloadThread.Create(UrlList[i], LocalPathList[i], ProgressBarList[i]); end; end; procedure TForm1.IdFTP1Work(ASender: TObject; AWorkMode: TWorkMode; AWorkCount: Int64); var Thread: TDownloadThread; begin Thread := TDownloadThread(CurrentThread); if Assigned(Thread) then Thread.Synchronize(Thread.DoUpdateProgress); end; ``` 在上述代码中,我们创建了一个名为 TDownloadThread 的自定义线程。这个线程包含了一个 IdFTP 或 IdHTTP 控件,以及一个进度条控件。在线程的 Execute 方法中,我们调用了 IdFTP 或 IdHTTP 的 Get 方法来下载文件。在 OnWork 事件中,我们使用 Synchronize 方法来更新进度条控件的值。在主窗体中,我们创建了多个进度条控件,并将每个控件与一个下载任务相关联。当下载完成时,线程会自动销毁。 需要注意的是,这里只是提供了一种实现方法,并不保证适用于所有情况。如果您遇到了问题,可以尝试使用其他方法来解决。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值