Loading an image from an URL
lazarus / 39-Graphics
----------------------------------------------------------------------
Dzandaa · 2025-06-18 09:46
Hi everybody,
for my CD database program, I'm trying to download this image from the
web and save it either as a file, a TImage, or a BGRABitmap. :
But I don't know how...
https://i.discogs.com/7njgT1NmTkfwyDxTxQSHHwzqaR9x_oDuzPOAY6Lq2PQ/rs:f
it/g:sm/q:40/h:150/w:150/czM6Ly9kaXNjb2dz/LWRhdGFiYXNlLWlt/YWdlcy9SLTE
wODk5/MzAtMTY1NjI0MTE5/NC0yNDk4LmpwZWc.jpeg
Code: Pascal [Select][+][-]window.onload = function(){var x1 =
document.getElementById("main_content_section"); if (x1) { var x =
document.getElementsByClassName("geshi");for (var i = 0; i Pict :=
TBGRABitmap.Create; HTTP := THTTPSend.Create; try
HTTP.Headers.Add('User-Agent: CDDatabase/1.0'); if
HTTP.HTTPMethod('GET', URL) then begin
Pict.LoadFromStream(HTTP.Document); // Error: The image format is
unknown end else TBStatus.Append('HTTP request failed.');
if(Pict <> nil) then FreeAndNil(Pict); finally
HTTP.Free; end; exit(Pict);
Thank you.
B->
----------------------------------------------------------------------
Thaddy · 2025-06-18 10:39
Try this:
Code: Pascal [Select][+][-]window.onload = function(){var x1 =
document.getElementById("main_content_section"); if (x1) { var x =
document.getElementsByClassName("geshi");for (var i = 0; i Pict :=
TBGRABitmap.Create;HTTP := THTTPSend.Create;try
HTTP.Headers.Add('User-Agent: CDDatabase/1.0'); if
HTTP.HTTPMethod('GET', URL) then begin HTTP.Document.Position :=
0; try Pict.LoadFromStream(HTTP.Document); except on
E: Exception do begin FreeAndNil(Pict);
TBStatus.Append('Image format not supported or corrupted: ' +
E.Message); end; end; end else begin FreeAndNil(Pict);
TBStatus.Append('HTTP request failed.'); end;finally
HTTP.Free;end;exit(Pict);Untested, will test it later.
----------------------------------------------------------------------
Dzandaa · 2025-06-18 10:54
Hi,
@Thaddy:
Thank you, but I got the same error in the same call
Code: Pascal [Select][+][-]window.onload = function(){var x1 =
document.getElementById("main_content_section"); if (x1) { var x =
document.getElementsByClassName("geshi");for (var i = 0; i
Pict.LoadFromStream(HTTP.Document); // Error: The image format is
unknown
B->
----------------------------------------------------------------------
etrusco · 2025-06-18 11:05
Did you check the image is fetched correctly (e.g tried saving the
stream to file)?
----------------------------------------------------------------------
Dzandaa · 2025-06-18 11:36
Hi,
@etrusco:
Yes i tried this:
Code: Pascal [Select][+][-]window.onload = function(){var x1 =
document.getElementById("main_content_section"); if (x1) { var x =
document.getElementsByClassName("geshi");for (var i = 0; i
HTTP.Document.SaveToFile('test');
And in the file, I have this:
Code: Text [Select][+][-]window.onload = function(){var x1 =
document.getElementById("main_content_section"); if (x1) { var x =
document.getElementsByClassName("geshi");for (var i = 0; i
301 Moved Permanently
301 Moved Permanently
cloudflare
I can open the link with Firefox without problem, I can save it and
it's O.K.
I'm not sure that is the good protocol to save an image from a link or
I miss something.
B->
----------------------------------------------------------------------
Thaddy · 2025-06-18 11:45
Switch over to TFPHttpClient, which supports redirects. (afaik,
ThttpSend too, but more cumbersome, hard to find)
The example I will add later will use that instead of THttpSend.
In a couple of hours I have the use of a real computer instead of a
phone.
----------------------------------------------------------------------
440bx · 2025-06-18 11:51
I have no idea how to use the HTTP class but, with "normal" (non-OOP)
http (say WinHTTP on Windows), you need to tell the server which types
your app can handle.
Normally, you see a call to WinHttpOpenRequest that tells the server
which types your app accepts. If you don't tell the server you can
accept pictures, the server will not send a picture. That might be
the problem in your code because I don't see anywhere anything that
informs the server what your code can accept. OTH, I have no idea what
the equivalent of WinHttpOpenRequest is in the HTTP class but, that
might the problem in your code.
HTH.
----------------------------------------------------------------------
olatov · 2025-06-18 11:52
Quick guess (which can be incorrect) is that you might have a http://
scheme on the URL, to which Cloudflare responds with a 301 https
redirection, that THTTPSend can't handle on its own. If this is the
case, then changing http:// to https:// should help.
----------------------------------------------------------------------
Dzandaa · 2025-06-18 13:15
Hi,
I also think there is a redirection problem.
Any help is welcome.
B->
----------------------------------------------------------------------
Fred vS · 2025-06-18 13:34
Quote from: Dzandaa on June 18, 2025, 03:15:15 pmHi,
I also think there is a redirection problem.
Any help is welcome.
B->
Hello neighbor!.
Maybe you can take inspiration from Simple Web Player.
Take a look at: procedure twebstreamerfo.getpicture(aurl: string);
line 1772 : this code.
----------------------------------------------------------------------
Thaddy · 2025-06-18 14:02
Good tip Fred!
BTW: the promised minimal example:Code: Pascal
[Select][+][-]window.onload = function(){var x1 =
document.getElementById("main_content_section"); if (x1) { var x =
document.getElementsByClassName("geshi");for (var i = 0; i {$mode
delphi}{$ifdef windows}{$apptype console}{$endif}uses classes,
fphttpclient, openSSL, opensslsockets;var Client:
TFPHttpClient;begin Client := TFPHttpClient.Create(nil); try
Client.RequestHeaders.Add('User-Agent: CDDatabase/1.0');
Client.AllowRedirect := true;
writeln(Client.Get('https://i.discogs.com/'));// your query goes here
too finally Client.Free; end;end.
You did not give us the right query, so I left that out, but at least:
there's your connection with redirects.
I used OpenSSL 3.5 and FPC trunk at 64 bit.
My previous stream code should easily integrate.
I have no use for it, but this establishes a proven connection.
----------------------------------------------------------------------
Thaddy · 2025-06-18 14:14
Note this particular website it very sensitive to what it believes
scraping attempts and may return a 403 if you test too many times.
----------------------------------------------------------------------
Dzandaa · 2025-06-18 14:39
Hi,
@neighbor
Thank you Fred, it works finally !!!
Here is my code:
Code: Pascal [Select][+][-]window.onload = function(){var x1 =
document.getElementById("main_content_section"); if (x1) { var x =
document.getElementsByClassName("geshi");for (var i = 0; i function
GetURLPicture(URL: string): TBGRABitmap;var amem: Tmemorystream; Pict:
TBGRABitmap;begin TBStatus.Append('URL ' +
URL); InitSSLInterface; amem := Tmemorystream.Create; try
MyHTTPClient.Get(URL, amem); amem.Position := 0; Pict :=
TBGRAbitmap.Create(amem); sleep(100); except on E: Exception do
begin TBStatus.Append('image failed: ' + E.Message);
exit(nil); end; end; amem.Free; Exit(Pict);end;
MyHTTPClient is a TFPHTTPClient component
Also Thank you Thaddy, we arrived at the same result
Now doing the same with Musicbrainz
Thank you all.
B->
----------------------------------------------------------------------
Thaddy · 2025-06-18 14:42
Good news!
----------------------------------------------------------------------
Remy Lebeau · 2025-06-18 16:21
Quote from: 440bx on June 18, 2025, 01:51:44 pmwith "normal" (non-OOP)
http (say WinHTTP on Windows), you need to tell the server which types
your app can handle.
Normally, you see a call to WinHttpOpenRequest that tells the server
which types your app accepts. If you don't tell the server you can
accept pictures, the server will not send a picture.
That is not how HTTP works. If a client does not specify what it
accepts, the server must assume the client can accept everything.
This is explicitly stated in the HTTP specs:
RFC 2616:
QuoteThe Accept request-header field can be used to specify certain
media types which are acceptable for the response... If no Accept
header field is present, then it is assumed that the client accepts
all media types.
RFC 7231
QuoteThe "Accept" header field can be used by user agents to specify
response media types that are acceptable... A request without any
Accept header field implies that the user agent will accept any media
type in response.
It is advisable to tell the server what you want to accept, but it is
not required to do so. But, if you don't specify it, then you need to
be prepared to handle other kinds of data that you don't want.
----------------------------------------------------------------------
Fred vS · 2025-06-18 16:29
Quote from: Dzandaa on June 18, 2025, 04:39:23 pmHi,
@neighbor
Thank you Fred, it works finally !!!