从web加载png图像( Delphi fmx)

voj3qocg  于 2022-11-23  发布在  其他
关注(0)|答案(3)|浏览(164)

我想从网络上加载png图像,但是使用下面的代码,并不是所有的图像都能正确地进入流中(在网页浏览器中发布url时,例如edge,确实会正确地给予图像)。例如,代码中的第一个url会给出加载位图失败的错误(在流中FSize只有14?),而第二个URL没有给予问题,有没有人知道如何正确下载第一个URL?
为了使这段代码正常工作,在窗体上放置了一个TButton和一个TImage。
在使用中添加了HttpClientComponent。我使用的是 Delphi 10.3.3.fmx。
谢了杰拉德

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;
tquggr8v

tquggr8v1#

OpenStreetMap图块服务器的问题是UserAgent。您必须将默认值更改为服务器可接受的值。我检查了许多可能性,似乎除了默认值TNetHTTPClient外,几乎任何值都有效。请参阅此Wikipedia article了解详细信息。
为此,您需要添加以下行

httpCli.UserAgent := 'Delphi/4.0 (compatible; Delphi; HttpClient)';

我的代码版本包括HTTP状态代码检查,如下所示:

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;
xbp102n0

xbp102n02#

在HTTP上操作时,你必须检查HTTP服务器是否能满足你的请求(状态码200,根据RFC7231,§ 6.3.1)或者是否出现任何错误。在你的情况下,请求URI并确保看到来自服务器的内容可以通过wget

wget -S --content-on-error https://a.tile.openstreetmap.org/11/1050/674.png

这将打印服务器的响应头,并在任何情况下创建一个文件来保存有效负载。响应头如下(摘录):

HTTP/1.1 403 Forbidden
Content-Length: 14

意思是:不允许您查询该资源(HTTP状态代码403)。有效负载保存在一个大小为14字节的文件中,包含以下14个ASCII字符的文本:

Access denied.

琐事:最小的有效PNG文件大小至少为67字节(读取"Smallest possible transparent PNG" by Gareth Rees .

o8x7eapl

o8x7eapl3#

这是fpiete答案的一个变体,我发现这种方法更简单,例如,不需要创建TMemoryStream对象。
您可以使用RESTRequest4D库来处理请求。使用方法非常简单,我发现它比常规的HTTP客户端更直观。

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;

相关问题