AGB  ·  Datenschutz  ·  Impressum  







Anmelden
Nützliche Links
Registrieren
Zurück Delphi-PRAXiS Programmierung allgemein Multimedia httpCLI: Download PNG funktioniert nicht, JPG geht
Thema durchsuchen
Ansicht
Themen-Optionen

httpCLI: Download PNG funktioniert nicht, JPG geht

Ein Thema von Siggi · begonnen am 6. Apr 2019 · letzter Beitrag vom 9. Apr 2019
Antwort Antwort
Siggi

Registriert seit: 19. Jun 2004
Ort: Lollar
52 Beiträge
 
Delphi 11 Alexandria
 
#1

httpCLI: Download PNG funktioniert nicht, JPG geht

  Alt 6. Apr 2019, 21:12
Hallo zusammen,

ich nutze schon länger einen einfache Code, der mir ein JPG holt und in eine TJPegImage mit LoadFromStream einfügt.
Jetzt gibt es aber auch PNG-Bilder und das Einfügen in ein TPNGObject geht nicht. Die heruntergeladene Grafik ist definitiv eine PNG. Ich habe das gleiche mal mit Indy (IdHttp) getestet, da geht es. Ich muss im dieser Applikation aber die httpCLI-Komponente von Overbyte verwenden, daher ist die einfachste Lösung (verwende Indy) leider nicht möglich .

Zusammenfassend:
- mit Indy kann ich JPG und PNG herunterladen und den geladenen MemoryStream mit LoadFromStream in einem TJPEGImage bzw. einem TPNGObject einfügen .
- mit httpCLI kann ich das nur mit einem JPG, beim selben PNG das mit Indy funktioniert, wird mir im Code mit httpCLI ein ungültiger Header gemeldet .

Hier der Code mit httpCLI: (einige unnötige Zeilen (Protokollierung) rausgeworfen, so ist es übersichtlicher.)

Delphi-Quellcode:
Procedure GetPicture(ImageURL:String; var image:TJPEGImage);
Var
  Data: TMemoryStream;
  png: TPNGObject;
  tbmp: TBitMap;
  SslHttpCli1: TSslHttpCli;
  SslContext1: TSslContext;
begin
  if (ImageURL>'') then
  begin
    Data := TMemoryStream.Create;
    try
      SslHttpCli1 := TSslHttpCli.Create(nil);
      SslContext1 := TSslContext.Create(nil);
      SslContext1.SslCipherList := 'ALL:!ADH:RC4+RSA:+SSLv2:@STRENGTH';
      SslContext1.SslECDHMethod := sslECDHNone;
      SslContext1.SslVerifyPeerModes := [SslVerifyMode_PEER];
      SslContext1.SslVersionMethod := sslBestVer;
      SslHttpCli1.SslContext := SslContext1;
      SslHttpCli1.URL := ImageURL;
      SslHttpCli1.RcvdStream := Data;
      try
        SslHttpCli1.Get;
        Data.Position := 0; //stream-position auf 0 setzen
        if TypeToStr(GetImageType(Data)) ='Image/JPEGthen
          Image.LoadFromStream(Data) // <--- das funktioniert !!!
        else if TypeToStr(GetImageType(Data)) ='Image/PNGthen
        begin
          png := TPNGObject.Create;
          tbmp:=TBitMap.Create;
          try
            png.LoadFromStream(Data); // <--- das funktioniert nicht, Fehlermeldung wegen ungültigem Header, selbe URL mit idHTTP (Indy) funktioniert.
            tbmp.Assign(png);
            image.Assign(tbmp);
          finally
            tbmp.Free;
            png.Free;
          end;
        end
        else
          showMessage('unbekannter Grafiktyp');
      except
        on E: Exception do
        begin
          MessageDlg(E.Message, mtWarning, [mbOK], 0);
        end;
      end;
    finally
      Data.Free;
      SslHttpCli1.Free;
      SslContext1.Free;
    end;
  end;
end;
Zum Vergleich der Code mit Indy, da geht's:
Delphi-Quellcode:
Procedure GetPicture(ImageURL:String; var image:TJPEGImage);
var
  MS: TMemoryStream;
  idHttp1:TIdHttp;
  sslIOHandler : TIdSSLIOHandlerSocketOpenSSL;
  png: TPNGObject;
  tbmp: TBitMap;
begin
  // Bild laden
  if ImageURL <> 'then
  begin
    MS := TMemoryStream.Create;
    IdHttp1 := TIdHTTP.Create(nil);
    if (AnsiUpperCase(copy(ImageURL, 1, 5)) = 'HTTPS') then
    begin
      sslIOHandler := frmInternetLookup.IdSSLIOHandlerSocketOpenSSL1; //TIdSSLIOHandlerSocketOpenSSL.Create(nil);
      sslIOHandler.PassThrough:=true;
      sslIOHandler.OnStatusInfo := frmInternetLookup.IdSSLIOHandlerSocketOpenSSL1.OnStatusInfo;
      IdHttp1.IOHandler := sslIOHandler;
    end;
    SetProxyData(IdHttp1);

    try
      IdHttp1.Get(ImageURL, MS);
      MS.Position := 0;
      if IdHTTP1.Response.ContentType = 'image/jpegthen
        Image.LoadFromStream(MS) // <--- hier funktioniert sowohl das...
      else if IdHTTP1.Response.ContentType = 'image/pngthen
      begin
        png := TPNGObject.Create;
        tbmp := TBitmap.Create;
        try
          png.LoadFromStream(MS); // <--- und das geht hier auch, nur bei httpCLI nicht...
          tbmp.Assign(png);
          image.Assign(tbmp);
        finally
          tbmp.Free;
          png.Free;
        end;
      end;
    except
      // entfernt
    end;
    MS.Free;
  end;
end;
Hat jemand einen Tipp für mich, wo ich ansetzen kann, um die Ursache zu finden?

.. Ergänzung: das Image liegt unter http://books.google.com/books/conten...source=gbs_api

Danke und Gruß,
Siggi

Geändert von Siggi ( 6. Apr 2019 um 21:19 Uhr)
  Mit Zitat antworten Zitat
Delphi.Narium

Registriert seit: 27. Nov 2017
2.415 Beiträge
 
Delphi 7 Professional
 
#2

AW: httpCLI: Download PNG funktioniert nicht, JPG geht

  Alt 6. Apr 2019, 21:29
Was macht GetImageType? Wird dadrin eventuell die Position im Stream verändert?

Dann eventuell
Delphi-Quellcode:
         try
            ///////////////
            Data.Position := 0; // <-- an den Anfang des Streams gehen.
            ///////////////
            png.LoadFromStream(Data); // <--- das funktioniert nicht, Fehlermeldung wegen ungültigem Header, selbe URL mit idHTTP (Indy) funktioniert.
Ansonsten testweise:
Delphi-Quellcode:
Data.SaveToFile('xxx.png');
png.LoadFromFile('xxx.png');
Geht das?
Wenn nein, mit 'nem anderen Programm prüfen, ob der Stream eine vernünftige PNG-Datei enthält.
  Mit Zitat antworten Zitat
Siggi

Registriert seit: 19. Jun 2004
Ort: Lollar
52 Beiträge
 
Delphi 11 Alexandria
 
#3

AW: httpCLI: Download PNG funktioniert nicht, JPG geht

  Alt 6. Apr 2019, 22:14
hmmm, saveToFile / LoadFromFile geht. Dann sollte der selbe Stream ohne "Zwischenspeichern" aber doch auch gleich funktionieren .
Rätselhaft, aber so habe ich zumindest einen Workaround.
Delphi-Quellcode:
          Data.SaveToFile(getTempDir+'\Image.png');
          png.LoadFromFile(getTempDir+'\Image.png');
erst mal danke, mal sehen ob ich noch rausfinde, warum das nicht auch ohne Umweg über die Datei geht.

Gruß,
Siggi
  Mit Zitat antworten Zitat
Delphi.Narium

Registriert seit: 27. Nov 2017
2.415 Beiträge
 
Delphi 7 Professional
 
#4

AW: httpCLI: Download PNG funktioniert nicht, JPG geht

  Alt 6. Apr 2019, 22:40
Setz' bitte mal 'nen Breakpoint vor png.LoadFromStream(Data) und debugge Dich da rein. Die ersten acht Byte des Streams müssten #137 #80 #78 #71 #13 #10 #26 #10 bzw. $89 $50 $E4 $47 $0D $0A $1A $0A sein oder die ersten vier als ASCII ‰PNG und Position von Data muss 0 sein.
  Mit Zitat antworten Zitat
Siggi

Registriert seit: 19. Jun 2004
Ort: Lollar
52 Beiträge
 
Delphi 11 Alexandria
 
#5

AW: httpCLI: Download PNG funktioniert nicht, JPG geht

  Alt 7. Apr 2019, 12:00
sowohl der MemoryStream aus IdHTTP (Indy) als auch aus httpCLI (Overbyte) fangen so an:

Zitat:
89504E470D0A1A0A0000000D4948445200000080000000C208 020000000ECC5DFB0000000373424954080808DBE14FE00000
Auch ein kompletter Vergleich der Byte-weise in Hex-Strings umgewandelten Streams aus IDHTTP und httpCLI in Notepad++ ergab keine Unterschiede.

Ich suche nicht weiter und mache das jetzt unschön aber funktionierend so:
Delphi-Quellcode:
          try
            png.LoadFromStream(Data);
          except // wenn es nicht geht -> Umweg über Datei
            Data.SaveToFile(getTempDir+'\Image.png');
            png.LoadFromFile(getTempDir+'\Image.png');
          end;
und das steckt nochmals in einem try..except..end für den Fall, dass auch das schief geht und zumindest eine verständliche Fehlermeldung und ein Logeintrag erfolgen.

Viele Grüße,
Siggi
  Mit Zitat antworten Zitat
TurboMagic

Registriert seit: 28. Feb 2016
Ort: Nordost Baden-Württemberg
2.822 Beiträge
 
Delphi 12 Athens
 
#6

AW: httpCLI: Download PNG funktioniert nicht, JPG geht

  Alt 7. Apr 2019, 21:17
Es gibt im englischen Teil der DP jetzt auch ein ICS Forum!
Vielleicht mal da nachfragen?
  Mit Zitat antworten Zitat
Michael II

Registriert seit: 1. Dez 2012
Ort: CH BE Eriswil
721 Beiträge
 
Delphi 11 Alexandria
 
#7

AW: httpCLI: Download PNG funktioniert nicht, JPG geht

  Alt 8. Apr 2019, 19:24
So lädst du ein PNG in einen Stream und von dort direkt in ein TPngImage.

TImage, THttpCli, TButton auf Form ziehen, uses mit pngimage ergänzen.

Delphi-Quellcode:

uses …. pngimage;

function TForm80.getpngimage( quelle : string; png : TPngImage ):boolean;
var tm : TMemoryStream;
begin
  tm := TMemoryStream.Create;
 try
  httpcli1.RcvdStream := tm;
  httpcli1.URL := quelle;
  httpCli1.Get;
  tm.Position := 0;
  png.LoadFromStream( tm );
 finally
  tm.free;
 end;
end;

Aufruf:

Delphi-Quellcode:
  

procedure TForm80.Button1Click(Sender: TObject);
var quelle : string;
    hpng : TPngImage;
begin
  quelle := 'http://pngimg.com/uploads/olives/olives_PNG14287.png';
  hpng := TPngImage.Create;
 try
  getpngimage( quelle, hpng );
  image1.Picture.Assign( hpng );
 finally
  hpng.Free;
 end;
end;
Ich habe gerade gemerkt, dass den Funktionen noch kein Result zugewiesen wird . Sollte man noch tun.

Natürlich solltest du den Code erweitern - ist nur eine kurze Demo, welche funktioniert.
[Wenn du eine Anwendung schreibst, welche immer wieder die gleichen URLs auf neue Version abfragt, dann lohnt es sich die Bilder (etc.) zu "cachen". Beim Abrufen der Daten vom Server kannst du dann via HeaderData prüfen, ob die Datei bereits lokal vorhanden ist und falls Ja, den Download abbrechen.


Und wenn du Datei speichern willst:

Delphi-Quellcode:
function TForm80.geturl( quelle, ziel : string ):boolean;
var tf : TFileStream;
begin
  tf := TFileStream.Create( ziel, fmCreate or fmOpenWrite );
 try
  httpcli1.RcvdStream := tf;
  httpcli1.URL := quelle;
  httpCli1.Get;
 finally
  tf.free;
 end;
end;
Michael Gasser

Geändert von Michael II ( 8. Apr 2019 um 19:50 Uhr)
  Mit Zitat antworten Zitat
Rolf Frei

Registriert seit: 19. Jun 2006
629 Beiträge
 
Delphi 11 Alexandria
 
#8

AW: httpCLI: Download PNG funktioniert nicht, JPG geht

  Alt 9. Apr 2019, 11:47
Ich habe auch die Vermutung, dass GetImageType etwas am Position des Streams verändert. Daher mache anstatt den 2 GetImageType Aufrufen nur einen wie folgt:

Code:
       
s := TypeToStr(GetImageType(Data));      
if s = 'Image/JPEG' then
  Image.LoadFromStream(Data) // <--- das funktioniert !!!
else if s = 'Image/PNG' then
...
  Mit Zitat antworten Zitat
Antwort Antwort


Forumregeln

Es ist dir nicht erlaubt, neue Themen zu verfassen.
Es ist dir nicht erlaubt, auf Beiträge zu antworten.
Es ist dir nicht erlaubt, Anhänge hochzuladen.
Es ist dir nicht erlaubt, deine Beiträge zu bearbeiten.

BB-Code ist an.
Smileys sind an.
[IMG] Code ist an.
HTML-Code ist aus.
Trackbacks are an
Pingbacks are an
Refbacks are aus

Gehe zu:

Impressum · AGB · Datenschutz · Nach oben
Alle Zeitangaben in WEZ +1. Es ist jetzt 03:53 Uhr.
Powered by vBulletin® Copyright ©2000 - 2024, Jelsoft Enterprises Ltd.
LinkBacks Enabled by vBSEO © 2011, Crawlability, Inc.
Delphi-PRAXiS (c) 2002 - 2023 by Daniel R. Wolf, 2024 by Thomas Breitkreuz