Recent

Author Topic: Resolvido : Problema idhttp.get() Stream png retornando erro wrong image format  (Read 323 times)

filipe080282

  • Newbie
  • Posts: 3
 >:(
Estou com um problema que está me deixando careca, caso algum dos amigos possa me ajudar tenho uma procedure que dá um get com idhhtp e retorna um memorystream que desejo pegar para capturar uma imagem de uma url que recebo de uma variavel.

Code: Pascal  [Select]
  1. procedure TForm1.CarregaImagem2(url: String; Apicture: TPicture);
  2. var
  3.   iHttpImg : TIdHTTP;
  4.   imgStream : TMemoryStream;
  5.   pngImage  : TPortableNetworkGraphic;
  6.   aString   : String;
  7. begin
  8.      iHttpImg := TIdHTTP.Create;
  9.      imgStream := TMemoryStream.Create;
  10.  
  11.      pngImage := TPortableNetworkGraphic.Create;
  12.      iHttpImg.Request.ContentType := 'text/plain';
  13.      iHttpImg.Request.UserAgent := 'Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:56.0; Waterfox) Gecko/20100101 Firefox/56.2.3';
  14.  
  15.      ShowMessage(url);
  16.  
  17.      iHttpImg.Get(url,imgStream);
  18.  
  19.      //imgStream.Position:= 0;
  20.  
  21.      //imgStream.Seek(0,soFromBeginning);
  22.      imgStream.Seek(0,soFromBeginning);
  23.  
  24.      pngImage.LoadFromStream(imgStream);
  25.  
  26.      APicture.Assign(pngImage);
  27. end;


Aqui vai a chamada da procedure


Code: Pascal  [Select]
  1. procedure TForm1.btnCarregaImagem2Click(Sender: TObject);
  2. begin
  3.   CarregaImagem2('https://cdn-cosmos.bluesoft.com.br/products/'+edtCodbarra.Text,Image1.Picture);
  4. end;  

Mas na hora do loadfrom stream dá erro wrong image format

Será que alguem pode me ajudar com esse código ?
« Last Edit: November 14, 2019, 12:27:25 pm by filipe080282 »

Handoko

  • Hero Member
  • *****
  • Posts: 3237
  • My goal: build my own game engine using Lazarus
Hello filipe080282,
Welcome to the forum.

Have you tried the code on a non-secure http site? I heard recently there were some issues to fetch data on a secure https site on Linux OS. Did you run it on Ubuntu? You can try to search the forum for more information, or maybe test the code on a non-secure site first.

Remy Lebeau

  • Hero Member
  • *****
  • Posts: 680
    • Lebeau Software
The error is coming from pngImage.LoadFromStream(), which means TIdHTTP.Get() did its job.  So this is not really an issue with Indy itself, but rather with the HTTP response.  The SSL/TLS portion worked fine, or else you would have gotten an error from TIdHTTP.Get() instead.

Obviously, the HTTP server is not delivering PNG data like you are expecting, but you are not doing any kind of validation before attempting to load the stream into TPortableNetworkGraphic.  What is the actual value of the TIdHTTP.Response.ContentType property after TIdHTTP.Get() is done?

What is the actual value of edtCodbarra.Text that you are testing with?  So that we can see for ourselves what the server is actually returning.

Also, you are leaking all of your objects you Create(), you need to Free() them when you are done using them.

Try something more like this:

Code: [Select]
procedure TForm1.CarregaImagem2(url: String; Picture: TPicture);
var
  iHttpImg : TIdHTTP;
  imgStream : TMemoryStream;
  pngImage  : TPortableNetworkGraphic;
begin
  ShowMessage(url);

  pngImage := TPortableNetworkGraphic.Create;
  try
    imgStream := TMemoryStream.Create;
    try     
      iHttpImg := TIdHTTP.Create;
      try
        iHttpImg.Request.UserAgent := 'Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:56.0; Waterfox) Gecko/20100101 Firefox/56.2.3';
        iHttpImg.Request.Accept := 'image/png';

        iHttpImg.Get(url, imgStream);

        if not IsHeaderMediaType(iHttpImg.Response.ContentType, 'image/png') then
         raise Exception.Create('Incorrect image type');
      finally
        iHttpImg.Free;
      end;
     
      imgStream.Position := 0;
      pngImage.LoadFromStream(imgStream);
    finally
      imgStream.Free;
    end;
     
    Picture.Assign(pngImage);
  finally
    pngImage.Free;
  end;
end;

Or maybe something like this:

Code: [Select]
procedure TForm1.CarregaImagem2(url: String; Picture: TPicture);
var
  iHttpImg : TIdHTTP;
  imgStream : TMemoryStream;
  fileExt: string;
begin
  ShowMessage(url);

  imgStream := TMemoryStream.Create;
  try     
    iHttpImg := TIdHTTP.Create;
    try
      iHttpImg.Request.UserAgent := 'Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:56.0; Waterfox) Gecko/20100101 Firefox/56.2.3';
      iHttpImg.Request.Accept := 'image/*';

      iHttpImg.Get(url, imgStream);

      if not IsHeaderMediaType(iHttpImg.Response.ContentType, 'image') then
         raise Exception.Create('Incorrect image type');

      fileExt := ExtractFileExt(ExtractHeaderSubItem(iHttpImg.Response.ContentDisposition, 'filename', QuoteHTTP));
      if fileExt = '' then
        fileExt := ExtractFileExt(ExtractHeaderSubItem(iHttpImg.Response.ContentType, 'name', QuoteHTTP));
      if fileExt = '' then
        fileExt := GetMIMEDefaultFileExt(ExtractHeaderItem(iHttpImg.Response.ContentType));
      if fileExt = '' then
        raise Exception.Create('Unknown file extension');
    finally
      iHttpImg.Free;
    end;

    imgStream.Position := 0;
    Picture.LoadFromStreamWithFileExt(imgStream, fileExt);
  finally
    imgStream.Free;
  end;
end;
Remy Lebeau
Lebeau Software - Owner, Developer
Internet Direct (Indy) - Admin, Developer (Support forum)

filipe080282

  • Newbie
  • Posts: 3
Agradeço aos amigo pela ajuda, porem ainda não cheguei a solução, segui as instruções do amigo Remy Lebeau, mas sempre dá um erro com imagem formato invalido.

a url completa da requisição no get ficaria assim
Code: Pascal  [Select]
  1. iHttpImg.Get('https://cdn-cosmos.bluesoft.com.br/products/7891910000197',imgStream);
  2.  

se eu colocar a url dentro do metodo dessa forma funciona e traz a imagem e consigo atribuir ao timage.

mas se eu passo por variavel dessa forma

Code: Pascal  [Select]
  1. procedure TForm1.CarregaImagem3(url: String; Apicture: TPicture);
  2. var
  3.   iHttpImg : TIdHTTP;
  4.   imgStream : TMemoryStream;
  5.   fileExt: string;
  6. begin
  7.   ShowMessage(url);
  8.  
  9.   imgStream := TMemoryStream.Create;
  10.   try
  11.     iHttpImg := TIdHTTP.Create;
  12.     try
  13.       iHttpImg.Request.UserAgent := 'Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:56.0; Waterfox) Gecko/20100101 Firefox/56.2.3';
  14.       iHttpImg.Request.Accept := 'image/*';
  15.  
  16.       iHttpImg.Get(url.Trim, imgStream);
  17.       {
  18.       if not IsHeaderMediaType(iHttpImg.Response.ContentType, 'image') then
  19.          raise Exception.Create('Incorrect image type');
  20.  
  21.       fileExt := ExtractFileExt(ExtractHeaderSubItem(iHttpImg.Response.ContentDisposition, 'filename', QuoteHTTP));
  22.       if fileExt = '' then
  23.         fileExt := ExtractFileExt(ExtractHeaderSubItem(iHttpImg.Response.ContentType, 'name', QuoteHTTP));
  24.       if fileExt = '' then
  25.         fileExt := GetMIMEDefaultFileExt(ExtractHeaderItem(iHttpImg.Response.ContentType));
  26.       if fileExt = '' then
  27.         raise Exception.Create('Unknown file extension'); }
  28.     finally
  29.       iHttpImg.Free;
  30.     end;
  31.  
  32.     imgStream.Position := 0;
  33.     Apicture.LoadFromStreamWithFileExt(imgStream, 'png');
  34.   finally
  35.     imgStream.Free;
  36.   end;
  37. end;  

Code: Pascal  [Select]
  1. CarregaImagem3('https://cdn-cosmos.bluesoft.com.br/products/'+edtCodbarra.Text,Image1.Picture);
  2.  

No caso aqui o valor de edtcodBarra.text := 7891910000197

Resumindo se eu colocar o valor da url direto no ihttpImage.get()
Dessa forma funciona:
Code: Pascal  [Select]
  1. iHttpImg.Get('https://cdn-cosmos.bluesoft.com.br/products/7891910000197',imgStream);

Mas se for passado como uma variavel do tipo string não funciona:
Code: Pascal  [Select]
  1. iHttpImg.Get(url, imgStream);

oBS, Comentei a parte do tratamento de erro fileext pq senão já dá erro nessa parte:
Code: Pascal  [Select]
  1.  
  2.  if not IsHeaderMediaType(iHttpImg.Response.ContentType, 'image') then
  3.          raise Exception.Create('Incorrect image type');
  4.  
« Last Edit: November 13, 2019, 01:53:16 pm by filipe080282 »

Remy Lebeau

  • Hero Member
  • *****
  • Posts: 680
    • Lebeau Software
Yeah, you are going to have to ignore everything I said about handling the Content-Type and Content-Disposition response headers.  When I request the URL you mentioned, the server does not send those headers at all.

There is literally no difference at all between doing this:

Code: [Select]
iHttpImg.Get('https://cdn-cosmos.bluesoft.com.br/products/7891910000197',imgStream);
And doing this instead:

Code: [Select]
productID := '7891910000197';
url := 'https://cdn-cosmos.bluesoft.com.br/products/'+productID;
iHttpImg.Get(url,imgStream);

So something else has to be going on.  I have to suspect that edtCodbarra.Text is not returning what you are expecting.  Maybe there is extra whitespace characters present that you are not seeing?  Who knows, we can't see your screen.  You are just going to have to debug your code to see what characters your url variable actually contains.  That is the only thing that makes sense in this situation.

Have you tried using edtCodbarra.Text.Trim() instead of url.Trim()?  Maybe there is unexpected whitespace in front of the text.  That would not be removed when trimming the final url.
« Last Edit: November 13, 2019, 07:04:50 pm by Remy Lebeau »
Remy Lebeau
Lebeau Software - Owner, Developer
Internet Direct (Indy) - Admin, Developer (Support forum)

filipe080282

  • Newbie
  • Posts: 3
Obrigado a todos pela Ajuda, depois de muito quebrar a cabeça acabei descobrindo que o problema estava na imagem que eu estava buscando na url.

depois de  muito quebrar a cabeça percebi isso.

Muito obrigado a todos.