Delphi使用THTTPClient实现异步下载

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

uses System.Net.HttpClient,System.IOUtils; 

初始化必需的变量参数

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

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

  FClient := THTTPClient.Create; //初始化
  FClient.OnReceiveData := ReceiveDataEvent;//下载数据进度接收事件
  FClient.SecureProtocols := [THTTPSecureProtocol.TLS1,
    THTTPSecureProtocol.TLS11, THTTPSecureProtocol.TLS12];//协议类型 可自定义
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方法为实际的下载启动操作

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;

//接收下载的状态 包括自然下载成功或用户人为终止
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;方法可终止下载操作。

完整代码如下:

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 @ 2022-07-07 13:39  NE1620  阅读(780)  评论(0)    收藏  举报