Class TCastleDownload
Unit
CastleDownload
Declaration
type TCastleDownload = class(TComponent)
Description
Download an URL (possibly making an HTTP(S) request) asynchronously, without blocking the application. You can register a callback OnFinish or watch when the Status property changes from dsDownloading to dsError or dsSuccess to detect when this finished downloading.
Features:
The download can be observed (looking at Status, DownloadedBytes, TotalBytes).
When the downlad is finished, look at Contents (if success) or ErrorMessage (if error, that is Status = dsError).
We can read MIME type from server (can be used throughout our engine to designate file type).
For downloading (making a request) using HTTP, this is a handful of additional features, to support downloading from modern web servers and using REST APIs:
First of all, we support both HTTP and HTTPS on all platforms and compilers, through various backend (FpHttpClient, Indy, Delphi Net Client).
You can provide arbitrary HTTP headers using HttpHeader. For example, various REST APIs require you to provide some key to authenticate through a custom HTTP header.
You can specify any HttpMethod, like GET, POST, PUT and more. Default is naturally GET which is the standard method to just download the data.
For HTTP POST method, you can provide form data as HttpPostData.
You can provide input data for any request using HttpRequestBody. The most common use case is to provide a body for PUT requests, but it can be used for any request, e.g. to provide POST body overriding the HttpPostData.
Once the download finishes, you can read HttpResponseCode and HttpResponseHeaders.
By default, we follow HTTP/HTTPS redirects.
See examples:
asynchronous_download to download resources asynchronously, downloading a few URLs and at the same time displaying an animation and progress bar.
remote_logging to send logs to a remote server, using HTTP POST.
put_data to send HTTP PUT request.
And other examples in examples/network subdirectory.
Usage:
The download starts when you call Start. Be sure to configure the properties, including OnFinish, before calling Start, because in case of some protocols Start may immediately read everything and finish. When the download ends, the OnFinish is called and Status changes.
You can always just free an instance of this class, this will break the download immediately, if it's still in-progress.
The download continues while your application is running, because we use ApplicationProperties.OnUpdate mechanism. If your application uses TCastleWindow or TCastleControl, then this just works. Note that if you just want to wait for download to finish, you can use WaitForFinish method or just call simpler Download routine.
Do not worry whether this uses threads (or not) internally. All the methods and properties of this class should be accessed from the main thread, the same thread you use for all Castle Game Engine functions. And the OnFinish is called in the main thread, so you can handle it without worrying about threading.
Hierarchy
- TObject
- TPersistent
- TComponent
- TCastleDownload
Overview
Methods
Properties
Description
Methods
|
procedure DoFinish; virtual; |
Note that this may destroy our own instance. So never access our own fields / virtual methods after calling this.
|
|
constructor Create(AOwner: TComponent); override; |
This item has no description. |
|
destructor Destroy; override; |
This item has no description. |
|
procedure Start; |
Get the data. This starts downloading. Be sure to set Url and other necessary properties before calling this.
|
|
procedure WaitForFinish; |
Wait until status is no longer dsDownloading.
|
|
function HttpPostData: TStrings; |
Form data to send when HttpMethod = hmPost. Initially empty. Use the TStrings name/value mechanism to set the form, like
Download.HttpPostData.Values['my-form-key'] := 'my-form-value';
Download.HttpPostData.Append('my-form-key-2=my-form-value-2');
|
|
function PostData: TStrings; deprecated 'use HttpPostData'; |
Warning: this symbol is deprecated: use HttpPostData This item has no description. |
|
function HttpRequestBody: TMemoryStream; |
Request body to send along with the request. Most useful with PUT (to send data to save on the server side). May also be useful with POST (only when the HttpPostData key-value is not flexible enough) or other requests.
You can use various TStream methods to set the stream, like TStream.CopyFrom . The CastleClassUtils also has various helpers for stream, e.g. to write a String (AnsiString, UTF-8 encoding) to a stream use WriteStr(Download.HttpRequestBody, 'My content') .
Example usage:
program put_data;
uses
CThreads,
SysUtils,
OpenSSLSockets,
CastleUtils, CastleDownload, CastleClassUtils;
var
D: TCastleDownload;
begin
D := TCastleDownload.Create(nil);
try
D.Url := 'https://castle-engine.io/miscella/test_put.php';
D.HttpMethod := hmPut;
WriteStr(D.HttpRequestBody, '{ "test": "value" }');
D.Start;
D.WaitForFinish;
case D.Status of
dsError: Writeln('Error: ', D.ErrorMessage);
dsSuccess: Writeln('Success');
else raise EInternalError.Create('Unexpected status');
end;
Writeln('Response code: ', D.HttpResponseCode);
Writeln('Response body: ', ReadGrowingStreamToDefaultString(D.Contents));
finally FreeAndNil(D) end;
end.
Note: For some requests you may want to add HTTP headers like Content-Type etc. Do this using HttpHeader.
In case of POST requests, when this stream has non-empty contents (stream size > 0), it overrules the HttpPostData. That is, HttpPostData is completely ignored in this case. Reason: Internally, HttpPostData is just an alternative way to set HttpRequestBody .
TODO: We may change this behavior in the future, to make it such that using HttpPostData will automatically set also HttpRequestBody contents to represent the given POST data, immediately. This way the "overriding" will be "whatever is set last, wins". For now, never use both HttpPostData and HttpRequestBody at the same time.
TODO: For now this is supported only when using FPC (not Delphi), on desktop or Android platforms (not iOS yet). It should be trivial to make it work in other cases too, just let us know ( https://castle-engine.io/talk.php ).
|
|
procedure HttpHeader(const AKey, AValue: String); |
Add additional HTTP headers, e.g. User-Agent.
|
|
procedure AddHeader(const AKey, AValue: String); deprecated 'use HttpHeader'; |
Warning: this symbol is deprecated: use HttpHeader This item has no description. |
Properties
|
property FinalUrl: String read FFinalUrl; |
When the download has finished (with success or error), this is updated to "final" URL, after resolving HTTP/HTTPS redirects and castle-data:/ protocol.
|
|
property Options: TStreamOptions read FOptions write SetOptions; |
Options that configure the output stream. See TStreamOption for details.
|
|
property Status: TDownloadStatus read FStatus; |
Whether we finished the download (and if yes, was it an error or success).
|
|
property ErrorMessage: String read FErrorMessage; |
If the Status is dsError, this contains a detailed error message.
|
|
property Contents: TStream read FContents; |
The downloaded contents.
If the Status is dsSuccess, this is always set (never Nil ). In case of some protocols and some failures, the contents may be available (not Nil ) even when error occurred, that is when Status is dsError. E.g. when HTTP server returns an error, like 404, it also still sends the response contents.
This stream is owned by default (if OwnsContents) by this TCastleDownload instance, so it will become invalid when the TCastleDownload instance is freed.
|
|
property OwnsContents: boolean read FOwnsContents write FOwnsContents default true; |
Is the Contents owned by this TCastleDownload instance. Set this to False to be able to free this TCastleDownload instance and still keep the stream reference. It is your responsibility then to keep and free the Contents stream whenever you want.
|
|
property DownloadedBytes: Int64 read FDownloadedBytes; |
How many bytes were downloaded. Together with TotalBytes, you can use it e.g. to show a progress bar when downloading. This is always >= 0.
|
|
property TotalBytes: Int64 read FTotalBytes; |
How many bytes are expected to be downloaded, in total. -1 if unknown. Depending on the server answer, this may be known fairly quickly after starting the download, or if may not be known at all (until we finish the download). It's guaranteed that this is known (not -1) when Status = dsSuccess, in all other cases always be prepared that this may be equal -1.
|
|
property MimeType: String read FMimeType; |
As soon as the MIME type of the downloaded contents is known, this is set. It is guaranteed to be set when Status is dsSuccess, it *may* be determined earlier (when dsDownloading).
|
|
property HttpResponseCode: Integer read FHttpResponseCode; |
When Status is dsSuccess or dsError, and request was using HTTP or HTTPS, this contains the HTTP status code. It is always 200 on success.
|
|
property HttpResponseHeaders: TStrings read FHttpResponseHeaders; |
When Status is dsSuccess or dsError, and request was using HTTP or HTTPS, this contains the HTTP response headers. The NameValueSeparator is set to ':' which means you can use TStrings name/value mechanism to read the data, like this:
LastModified := Download.HttpResponseHeaders.Values['Last-Modified'];
Note that it is Nil in case of non-HTTP/HTTPS requests.
|
Generated by PasDoc 0.16.0-snapshot.