Reputation: 145
I would like to load png images from the web, but with the code below not all images do get correctly into the stream (while posting the url in a webbrowser, e.g. edge, does give the image correctly). For example, the first url in the code gives a loading bitmap failed error (in the stream FSize is only 14?), while the second url does not give a problem. Does anyone know how to download the first url correctly?
For this piece of code to work, a TButton and a TImage was put on a form.
System.Net.HttpClientComponent was added in the uses. I am using Delphi 10.3.3. fmx.
Thanks, Gerard
procedure TForm1.Button1Click(Sender: TObject);
var ms: TmemoryStream;
httpCli: TNetHTTPClient;
url: string;
begin
httpCli := TNetHTTPClient.Create(nil);
ms := TMemoryStream.Create();
url := 'https://a.tile.openstreetmap.org/11/1050/674.png';
// url := 'https://upload.wikimedia.org/wikipedia/commons/d/d5/Japan_small_icon.png';
httpCli.Get(url,ms);
ms.Position := 0;
Image1.Bitmap.LoadFromStream(ms);
ms.free;
httpCli.free;
end;
Upvotes: 4
Views: 2029
Reputation: 109
This is a variation of fpiete's answer. I found this way simpler, with no need to create the TMemoryStream
object, for example.
You can use the RESTRequest4D library for the request. The usage is very simple and I find it more intuitive than the regular HTTP client.
procedure TQRCodeForm.LoadImageFromURL;
var
LResponse: IResponse;
begin
LResponse := TRequest
.New
.BaseURL(ImageURL)
.Get;
if LResponse.StatusCode = 200 then
begin
MyTImage.Bitmap.LoadFromStream(LResponse.ContentStream);
end;
end;
Upvotes: 1
Reputation: 12292
The problem with the OpenStreetMap tile server is the UserAgent. You must change the default value to something acceptable by the server. I checked a number of possibilities and it looks like almost anything but default value of TNetHTTPClient
works. See this Wikipedia article for details.
To do that, you need to add the line
httpCli.UserAgent := 'Delphi/4.0 (compatible; Delphi; HttpClient)';
My version of your code which includes HTTP status code checking is the following:
procedure TForm1.Button1Click(Sender: TObject);
var
ms : TMemoryStream;
httpCli : TNetHTTPClient;
resp : IHTTPResponse;
url : String;
begin
httpCli := TNetHTTPClient.Create(nil);
try
httpCli.UserAgent := 'Delphi/4.0 (compatible; Delphi; HttpClient)';
ms := TMemoryStream.Create();
try
url := 'https://a.tile.openstreetmap.org/11/1050/674.png';
resp := httpCli.Get(url, ms);
if resp.StatusCode <> 200 then
Memo1.Lines.Add(Format('HTTP Error=%d %s',
[resp.StatusCode, resp.StatusText]))
else begin
ms.Position := 0;
Image1.Bitmap.LoadFromStream(ms);
end;
finally
ms.Free;
end;
finally
httpCli.Free;
end;
end;
Upvotes: 7
Reputation: 6099
When operating on HTTP you have to check if the HTTP server can satisfy your request (status code 200, as per RFC7231, § 6.3.1) or any error occured. In your case requesting that URI and making sure to see what comes from the server can be done with i.e. wget:
wget -S --content-on-error https://a.tile.openstreetmap.org/11/1050/674.png
This will print the server's response headers and in any case create a file that will hold the payload. The response headers are (excerpt):
HTTP/1.1 403 Forbidden
Content-Length: 14
Which means: you are not allowed to query that resource (HTTP status code 403). The payload is saved in a file sizing 14 bytes, containing this text in 14 ASCII characters:
Access denied.
Trivia: the smallest valid PNG file sizes at least 67 bytes (read "Smallest possible transparent PNG" by Gareth Rees.
Upvotes: 1