Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Load a png image from the web (delphi fmx)

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;
like image 526
Gerard Avatar asked Sep 05 '25 01:09

Gerard


2 Answers

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;
like image 112
fpiette Avatar answered Sep 07 '25 13:09

fpiette


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;
like image 23
Leo Avatar answered Sep 07 '25 15:09

Leo