Skip to content

📦 Progress to request of the stream, with options to cancel progress #244

@luisnt

Description

@luisnt

📝 Description:

It would be very useful to enhance TRESTRequest (or provide an extension) to support progress tracking for stream-based requests (especially downloads), with an optional cancel mechanism.


🚀 Motivation

When handling large file downloads (or uploads), providing real-time feedback to the user is important for usability. Additionally, the ability to cancel a long-running request is essential in modern applications, especially when dealing with limited bandwidth or mobile users.


✅ Expected Features

  • Event or callback for progress reporting during Stream downloads or uploads
    (e.g., OnProgress, OnDownloadProgress)
  • Ability to cancel the request gracefully from within the event
    (e.g., via a Cancel flag or method)
  • Optional integration with TTask, TThread, or another async approach to ensure non-blocking UI

💡 Simple example Use Case (Delphi)

uses
  Winapi.Windows,
  System.Classes, System.SysUtils, System.Threading,
  Vcl.Forms, Vcl.Dialogs,
  RESTRequest4D;

var
  CancelDownload: Boolean = False;

procedure DownloadWithProgress(const URL, FileName: string);
var
  FileStream: TFileStream;
  TotalSize: Int64;
  LastReported: TDateTime;
begin
  TTask.Run(procedure
  var
    HTTP: IResponse;
    Downloaded: Int64;
  begin
    try
      FileStream := TFileStream.Create(FileName, fmCreate);
      try
        Downloaded := 0;
        LastReported := Now;

        HTTP := TRequest.New
          .BaseURL(URL)
          .Accept('application/octet-stream')
          .StreamResponse(FileStream)
          .OnReceiveProgress(
            procedure(ATotal, ACurrent: Int64; var AAbort: Boolean)
            var
              Percent: Double;
            begin
              if ATotal > 0 then
                Percent := (ACurrent / ATotal) * 100
              else
                Percent := 0;

              // Update UI (simplified example)
              if SecondsBetween(LastReported, Now) >= 1 then
              begin
                TThread.Synchronize(nil,
                  procedure
                  begin
                    Application.ProcessMessages;
                    OutputDebugString(PChar(Format('Progress: %.2f%%', [Percent])));
                  end);
                LastReported := Now;
              end;

              AAbort := CancelDownload;
            end)
          .Get;

        if HTTP.StatusCode = 200 then
          ShowMessage('Download completed!')
        else
          ShowMessage('Download error: ' + HTTP.StatusText);
      finally
        FileStream.Free;
      end;
    except
      on E: Exception do
        TThread.Synchronize(nil,
          procedure
          begin
            ShowMessage('Error: ' + E.Message);
          end);
    end;
  end);
end;
 
procedure TForm1.btnDownloadClick(Sender: TObject);
const
  GitHubAssetURL = 'https://github.com/your-username/your-repo/releases/download/v1.0.0/yourfile.exe';
begin
  CancelDownload := False;
  DownloadWithProgress(GitHubAssetURL, 'C:\Temp\yourfile.exe');
end;

procedure TForm1.btnCancelarClick(Sender: TObject);
begin
  CancelDownload := True;
end;

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions