Delphi使用THTTPClient实现异步下载

首先在接口部分需要引用System.Net.HttpClient类

1
uses System.Net.HttpClient,System.IOUtils; 

初始化必需的变量参数

1
2
3
4
FClient: THTTPClient; //异步下载类
FGlobalStart: Cardinal; //全局计时
FAsyncResult: IAsyncResult; //set and get 异步调用的状态
FDownloadStream: TStream; //下载流

异步下载类的初始化:其中下方的ReceiveDataEvent方法表示响应下载的当前进度:滚动台、百分比等可视化内容可通过其展示给用户

1
2
3
4
FClient := THTTPClient.Create; //初始化
FClient.OnReceiveData := ReceiveDataEvent;//下载数据进度接收事件
FClient.SecureProtocols := [THTTPSecureProtocol.TLS1,
  THTTPSecureProtocol.TLS11, THTTPSecureProtocol.TLS12];//协议类型 可自定义
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
procedure ReceiveDataEvent(const Sender: TObject;
AContentLength, AReadCount: Int64; var Abort: Boolean);
var
  LTime: Cardinal;
  LSpeed: Integer;
begin
  LTime := TThread.GetTickCount - FGlobalStart;//片段事件
  if LTime = 0 then
    Exit;
  LSpeed := (AReadCount * 1000) div LTime;
//  TThread.Queue 将线程放入主线程main窗体执行 用于显示进度
  TThread.Queue(nil,
    procedure
    begin
      ProgressBarDownload.Value := AReadCount;
      LabelGlobalSpeed.Caption := Format('Global speed: %d KB/s',
        [LSpeed div 1024]);
    end);
end;

在窗体上放置了一个启动的button按钮,在buttononclick事件中调用SampleDownload方法。SampleDownload方法为实际的下载启动操作

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
procedure SampleDownload;
var
  URL: string;
  LResponse: IHTTPResponse;
  LFileName: string;
  LSize: Int64;
begin
  LFileName := EditFileName.Text; //下载文件存放地址
  try
    URL := EditUrl.Text; //下载地址
 
    LResponse := FClient.Head(URL); //获取请求头
    LSize := LResponse.ContentLength; //判断请求头的大小 是否请求成功
    Memo1.Lines.Add(Format('Head response: %d - %s', [LResponse.StatusCode,
      LResponse.StatusText]));//打印出请求状态 和 状态内容
    LResponse := nil; //释放请求头内容
    ProgressBarDownload.Maximum := LSize; //进度条的最大值 要注意的是vcl与fmx进度条maxium不同
    ProgressBarDownload.Minimum := 0; //进度条起点
    ProgressBarDownload.Value := 0; //进度条当前值
    LabelGlobalSpeed.Caption := 'Download speed: 0 KB/s';
 
    Memo1.Lines.Add(Format('Downloading: "%s" (%d Bytes) into "%s"',
      [EditFileName.Text, LSize, LFileName]));
 
    // Create the file that is going to be dowloaded
    FDownloadStream := TFileStream.Create(LFileName, fmCreate); //下载流初始化以及文件权限设置
    FDownloadStream.Position := 0; //下载流从起点开始 初始化
 
    // Start the download process
    FGlobalStart := TThread.GetTickCount;
    FAsyncResult := FClient.BeginGet(DoEndDownload, URL, FDownloadStream);//返回异步调用状态 以及 随时可控 可断
 
  finally
    BStopDownload.Enabled := FAsyncResult <> nil; //判断异步调用状态
    BStartDownload.Enabled := FAsyncResult = nil; //释放
  end;
end;<br><br>//接收下载的状态 包括自然下载成功或用户人为终止procedure DoEndDownload(const AsyncResult: IAsyncResult);
var
  LAsyncResponse: IHTTPResponse;
begin
  try
//判断异步调用的状态
    LAsyncResponse := THTTPClient.EndAsyncHTTP(AsyncResult);
//将此线程阻塞到主线程中去 在ui界面上告知用户操作状态
    TThread.Synchronize(nil,
      procedure
      begin
        if AsyncResult.IsCancelled then
          Memo1.Lines.Add('Download Canceled')
        else
        begin
          Memo1.Lines.Add('Download Finished!');
          Memo1.Lines.Add(Format('Status: %d - %s', [LAsyncResponse.StatusCode,
            LAsyncResponse.StatusText]));
        end;
 
        BStopDownload.Enabled := False;
        BStartDownload.Enabled := True;
      end);
  finally
    LAsyncResponse := nil;
    FreeandNil(FDownloadStream);
  end;
end;

放置了一个停止的Button按钮,在buttononclick中调用FAsyncResult.Cancel;方法可终止下载操作。

完整代码如下:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
unit DownloadForm;
 
interface
 
uses
  Winapi.Windows, Winapi.Messages, System.SysUtils, System.Variants,
  System.Classes, Vcl.Graphics,
  Vcl.Controls, Vcl.Forms, Vcl.Dialogs, System.Net.URLClient,
  System.Net.HttpClient, System.Net.HttpClientComponent, Vcl.ComCtrls,
  Vcl.StdCtrls, System.Types, Vcl.ExtCtrls;
 
type
  TFormDownload = class(TForm)
    Panel1: TPanel;
    Label1: TLabel;
    Label2: TLabel;
    EditFileName: TEdit;
    EditUrl: TEdit;
    BStartDownload: TButton;
    LabelGlobalSpeed: TLabel;
    BStopDownload: TButton;
    Panel2: TPanel;
    Memo1: TMemo;
    ProgressBarDownload: TProgressBar;
    procedure BStartDownloadClick(Sender: TObject);
    procedure ReceiveDataEvent(const Sender: TObject; AContentLength: Int64;
      AReadCount: Int64; var Abort: Boolean);
    procedure FormCreate(Sender: TObject);
    procedure FormDestroy(Sender: TObject);
    procedure BStopDownloadClick(Sender: TObject);
  private
    { Private declarations }
    FClient: THTTPClient;
    FGlobalStart: Cardinal;
    FAsyncResult: IAsyncResult;
    FDownloadStream: TStream;
    procedure SampleDownload;
    procedure DoEndDownload(const AsyncResult: IAsyncResult);
  public
    { Public declarations }
  end;
 
var
  FormDownload: TFormDownload;
 
implementation
 
uses System.IOUtils;
{$R *.dfm}
 
procedure TFormDownload.BStopDownloadClick(Sender: TObject);
begin
  (Sender as TButton).Enabled := False;
  FAsyncResult.Cancel;
end;
 
procedure TFormDownload.DoEndDownload(const AsyncResult: IAsyncResult);
var
  LAsyncResponse: IHTTPResponse;
begin
  try
    LAsyncResponse := THTTPClient.EndAsyncHTTP(AsyncResult);
    TThread.Synchronize(nil,
      procedure
      begin
        if AsyncResult.IsCancelled then
          Memo1.Lines.Add('Download Canceled')
        else
        begin
          Memo1.Lines.Add('Download Finished!');
          Memo1.Lines.Add(Format('Status: %d - %s', [LAsyncResponse.StatusCode,
            LAsyncResponse.StatusText]));
        end;
 
        BStopDownload.Enabled := False;
        BStartDownload.Enabled := True;
      end);
  finally
    LAsyncResponse := nil;
    FreeandNil(FDownloadStream);
  end;
end;
 
procedure TFormDownload.ReceiveDataEvent(const Sender: TObject;
AContentLength, AReadCount: Int64; var Abort: Boolean);
var
  LTime: Cardinal;
  LSpeed: Integer;
begin
  LTime := TThread.GetTickCount - FGlobalStart;
  if LTime = 0 then
    Exit;
  LSpeed := (AReadCount * 1000) div LTime;
  TThread.Queue(nil,
    procedure
    begin
      ProgressBarDownload.Value := AReadCount;
      LabelGlobalSpeed.Caption := Format('Global speed: %d KB/s',
        [LSpeed div 1024]);
    end);
end;
 
procedure TFormDownload.FormCreate(Sender: TObject);
begin
  FClient := THTTPClient.Create;
  FClient.OnReceiveData := ReceiveDataEvent;
  FClient.SecureProtocols := [THTTPSecureProtocol.TLS1,
    THTTPSecureProtocol.TLS11, THTTPSecureProtocol.TLS12];
end;
 
procedure TFormDownload.FormDestroy(Sender: TObject);
begin
  FDownloadStream.Free;
  FClient.Free;
end;
 
procedure TFormDownload.BStartDownloadClick(Sender: TObject);
begin
  BStartDownload.Enabled := False;
  SampleDownload;
end;
 
procedure TFormDownload.SampleDownload;
var
  URL: string;
  LResponse: IHTTPResponse;
  LFileName: string;
  LSize: Int64;
begin
  LFileName := EditFileName.Text;
  try
    URL := EditUrl.Text;
 
    LResponse := FClient.Head(URL);
    LSize := LResponse.ContentLength;
    Memo1.Lines.Add(Format('Head response: %d - %s', [LResponse.StatusCode,
      LResponse.StatusText]));
    LResponse := nil;
    ProgressBarDownload.Maximum := LSize;
    ProgressBarDownload.Minimum := 0;
    ProgressBarDownload.Value := 0;
    LabelGlobalSpeed.Caption := 'Download speed: 0 KB/s';
 
    Memo1.Lines.Add(Format('Downloading: "%s" (%d Bytes) into "%s"',
      [EditFileName.Text, LSize, LFileName]));
 
    // Create the file that is going to be dowloaded
    FDownloadStream := TFileStream.Create(LFileName, fmCreate);
    FDownloadStream.Position := 0;
 
    // Start the download process
    FGlobalStart := TThread.GetTickCount;
    FAsyncResult := FClient.BeginGet(DoEndDownload, URL, FDownloadStream);
 
  finally
    BStopDownload.Enabled := FAsyncResult <> nil;
    BStartDownload.Enabled := FAsyncResult = nil;
  end;
end;
 
end.

  

使用上述方法,便可使用Delphi完成异步下载~Delphi是真的强大~超级大爱

原文地址:https://www.cnblogs.com/ne1620/p/16454384.html

posted @   NE1620  阅读(642)  评论(0编辑  收藏  举报
相关博文:
阅读排行:
· TypeScript + Deepseek 打造卜卦网站:技术与玄学的结合
· Manus的开源复刻OpenManus初探
· AI 智能体引爆开源社区「GitHub 热点速览」
· 从HTTP原因短语缺失研究HTTP/2和HTTP/3的设计差异
· 三行代码完成国际化适配,妙~啊~
点击右上角即可分享
微信分享提示