how to convert idhttp downloaded image from extention to another? - delphi

i have this Thread that get image url from the web then save it to memory stream then save from memory stream To file
i needed to convert any image that downloaded to a gif image so i do something like this
unit downloadimgThread;
interface
uses Windows, SysUtils, Classes, dialogs, IdSSLOpenSSL, IdHttp, IdUri, System.AnsiStrings, Graphics, Jpeg, Vcl.Imaging.GIFImg, PNGImage;
type
TDownloadUpdateVisualEvent = procedure(Sender: TObject; Anameofimg: String;
var Aimagelocate: String) of object;
type
TURLDownload = class(TThread)
private
FOnUpdateVisual: TDownloadUpdateVisualEvent;
FURL: String;
Fnameofimg: string;
FPathImage: string;
FFileNameImage: string;
ImageName: string;
PathURL: string;
procedure DoUpdateVisual;
protected
procedure Execute; override;
public
constructor Create(Thrdid: Pointer; const AUrl: String;
Const AOutPathImages: string; AOnUpdateVisual: TDownloadUpdateVisualEvent;
Anameofimg: String); reintroduce;
property URL: string read FURL write FURL;
property PathImage: string read FPathImage;
property FileNameImage: string read FFileNameImage;
end;
var
URLDOWNLOAD: TURLDownload;
implementation
{ TURLDownload }
function JpgToGif(ms: TMemoryStream): Boolean;
var
gif: TGIFImage;
jpg: TJPEGImage;
begin
Result := False;
gif := TGIFImage.Create;
try
jpg := TJPEGImage.Create;
try
//jpg
ms.Position := 0;
jpg.LoadFromStream(ms);
jpg.DIBNeeded;
gif.Assign(jpg);
//save...
ms.Clear;
gif.SaveToStream(ms);
Result := True;
finally
jpg.Free;
jpg := nil;
end;
finally
gif.Free;
gif := nil;
end;
end;
constructor TURLDownload.Create(Thrdid: Pointer; const AUrl, AOutPathImages: string; AOnUpdateVisual: TDownloadUpdateVisualEvent; Anameofimg: String);
var
URI: TIdURI;
begin
inherited Create(false);
FreeOnTerminate := True;
FURL := AUrl;
FOnUpdateVisual := AOnUpdateVisual;
Fnameofimg := Anameofimg;
FPathImage := AOutPathImages;
URI := TIdURI.Create(AUrl);
try
ImageName := URI.Document;
PathURL := URI.path;
finally
URI.Free;
end;
end;
procedure TURLDownload.DoUpdateVisual;
begin
if Assigned(FOnUpdateVisual) then
FOnUpdateVisual(self, Fnameofimg, FFileNameImage);
end;
procedure TURLDownload.Execute;
var
aMs: TMemoryStream;
aIdHttp: TIdHttp;
IdSSL: TIdSSLIOHandlerSocketOpenSSL;
path: string;
dir: string;
SPEXT : String;
itsimage: string;
responsechk: Integer;
begin
dir := AnsiReplaceText(PathURL, '/', '');
if (ImageName = '') then
begin
exit;
end;
SPEXT := ExtractFileExt(ImageName);
ImageName := Copy(ImageName, 1, Length(ImageName) - Length(SPEXT));
path := PathImage + '\' + ImageName + '.gif';
if fileexists(path) then
begin
FFileNameImage := path;
if Assigned(FOnUpdateVisual) then
begin
Synchronize(DoUpdateVisual);
end;
exit;
end
else
if not fileexists(path) then
begin
aMs := TMemoryStream.Create;
aIdHttp := TIdHttp.Create(nil);
IdSSL := TIdSSLIOHandlerSocketOpenSSL.Create(nil);
try
IdSSL.SSLOptions.Method := sslvTLSv1;
IdSSL.SSLOptions.Mode := sslmUnassigned;
aIdHttp.HTTPOptions := [hoForceEncodeParams] + [hoNoProtocolErrorException];
aIdHttp.IOHandler := IdSSL;
aIdHttp.AllowCookies := True;
aIdHttp.Request.UserAgent := 'Mozilla/5.0 (Windows NT 6.1; WOW64; rv:12.0) Gecko/20100101 Firefox/12.0';
aIdHttp.HandleRedirects := True;
aIdHttp.RedirectMaximum := 3;
try
aIdHttp.Head(trim(FURL));
except
end;
itsimage := aIdHttp.Response.ContentType;
responsechk := aIdHttp.ResponseCode;
if responsechk <> 200 then
begin
FFileNameImage := 'error';
if Assigned(FOnUpdateVisual) then
begin
Synchronize(DoUpdateVisual);
end;
exit;
end;
if (itsimage = 'image/gif') then
begin
try
aIdHttp.Get(trim(FURL), aMs);
except
end;
aMs.SaveToFile(path);
end else if (itsimage = 'image/jpeg') then
begin
try
aIdHttp.Get(trim(FURL), aMs);
except
end;
if JpgToGif(aMs) then
begin
aMs.SaveToFile(path);
end;
end;
try
if aIdHttp.Connected then
aIdHttp.Disconnect;
except
end;
finally
aMs.Free;
IdSSL.Free;
aIdHttp.Free;
end;
end;
FFileNameImage := path;
if Assigned(FOnUpdateVisual) then
begin
Synchronize(DoUpdateVisual);
end;
end;
end.
in this unit i try to check if image type is jpg then convert it to gif and save it specifically at this line of code
if (itsimage = 'image/jpeg') then
begin
try
aIdHttp.Get(trim(FURL), aMs);
except
end;
if JpgToGif(aMs) then
begin
aMs.SaveToFile(path);
end;
// function to convert
function JpgToGif(ms: TMemoryStream): Boolean;
var
gif: TGIFImage;
jpg: TJPEGImage;
begin
Result := False;
gif := TGIFImage.Create;
try
jpg := TJPEGImage.Create;
try
//jpg
ms.Position := 0;
jpg.LoadFromStream(ms);
jpg.DIBNeeded;
gif.Assign(jpg);
//save...
ms.Clear;
gif.SaveToStream(ms);
Result := True;
finally
jpg.Free;
jpg := nil;
end;
finally
gif.Free;
gif := nil;
end;
end;
when i try to convert the image and save it the image saved is corrupted what could be the issue ?

There is a very simple solution for this. And that is to use FMX Bitmap instead of default VCL Bitmap as it allows automatic format recognition on load and automatic format choosing on save based on file extension of the file name you provide to SaveToFile method.
Here is a simple code that loads selected image chosen in OpenDialog into Memory stream first and then into Bitmap and then it saves the image into GIF format.
procedure TForm1.Button1Click(Sender: TObject);
var Bitmap: FMX.Graphics.TBitmap;
MS: TMemoryStream;
begin
if OpenDialog1.Execute then
begin
MS := TMemoryStream.Create;
MS.LoadFromFile(OpenDialog1.FileName);
Bitmap := FMX.Graphics.TBitmap.Create;
Bitmap.LoadFromStream(MS);
Bitmap.SaveToFile('D:\Proba.gif');
end;
end;
As you can see you only need just a few lines and you get ability to convert images between all supported formats.
You can see which ones are supported here:
http://docwiki.embarcadero.com/Libraries/XE8/en/FMX.Graphics.TBitmapCodecManager#Supported_Image_Formats
Just make sure you are indeed using FMX.Graphics.TBitmap by specifying the full namespace for the file in which it resided.
NOTE: Working on VCL application does not mean you can't use some of the functionality that is present in Fire Monkey.

Related

How load a base64 encrypted url in a TWebBrowser or TImage?

I have this url encrypted in base64 that is a animated QRCode.
How i can load it in a TWebBrowser (or TImage)? Thanks in advance.
Edit:
Here was my attempt, but without success:
uses
IdHTTP, IdSSLOpenSSL, GIFImg, ClipBrd;
type
TForm1 = class(TForm)
Button1: TButton;
Image1: TImage;
procedure Button1Click(Sender: TObject);
procedure FormCreate(Sender: TObject);
private
{ Private declarations }
public
{ Public declarations }
end;
var
Form1: TForm1;
implementation
{$R *.dfm}
function GetStrFromClipbrd: string;
begin
if Clipboard.HasFormat(CF_TEXT) then
Result := Clipboard.AsText
else
begin
ShowMessage('There is no text in the Clipboard!');
Result := '';
end;
end;
procedure TForm1.Button1Click(Sender: TObject);
var
MS: TMemoryStream;
IdHTTP1: TIdHTTP;
GIF: TGIFImage;
begin
MS := TMemoryStream.Create;
try
IdHTTP1 := TIdHTTP.Create;
try
GIF := TGIFImage.Create;
try
IdHTTP1.IOHandler := TIdSSLIOHandlerSocketOpenSSL.Create(IdHTTP1);
IdHTTP1.HandleRedirects := True;
IdHTTP1.Get(GetStrFromClipbrd, MS);
MS.Seek(0, soFromBeginning);
GIF.LoadFromStream(MS);
Image1.Picture.Assign(GIF);
(Image1.Picture.Graphic as TGIFImage).Animate := True;
//(Image1.Picture.Graphic as TGIFImage).AnimationSpeed := 500;
finally
FreeAndNil(GIF);
end;
finally
FreeAndNil(IdHTTP1);
end;
finally
FreeAndNil(MS);
end;
end;
procedure TForm1.FormCreate(Sender: TObject);
begin
Form1.DoubleBuffered := True;
end;
end.
data: is not a URL type you can request with TIdHTTP (or any other HTTP library), nor do you need to since all of the data is encoded directly in the URL itself. So simply extract the base64 portion and decode it using any base64 decoder of your choosing.
Since your code is already using Indy anyway, you could use its TIdDecoderMIME class in the IdCoderMIME unit to decode the base64 data to a binary stream, such as with the TIdDecoderMIME.DecodeStream() class procedure. Then you can load that stream into an appropriate TGraphic descendant (TGIFImage, TBitmap, etc), and then finally you can load that graphic into your TImage.
For example:
uses
IdGlobal, IdGlobalProtocols, IdCoderMIME, IdHTTP, IdSSLOpenSSL,
Graphics, GIFImg, JPEG, ClipBrd;
function GetStrFromClipbrd: string;
const
CTextFormat = {$IFDEF UNICODE}CF_UNICODETEXT{$ELSE}CF_TEXT{$ENDIF};
begin
if Clipboard.HasFormat(CTextFormat) then
Result := Clipboard.AsText
else
Result := '';
end;
procedure TForm1.Button1Click(Sender: TObject);
var
Graphic: TGraphic;
MS: TMemoryStream;
IdHTTP1: TIdHTTP;
URL, ContentType: string;
begin
URL := GetStrFromClipbrd;
if URL = '' then
begin
ShowMessage('There is no text in the Clipboard!');
Exit;
end;
Graphic := nil;
try
MS := TMemoryStream.Create;
try
if TextStartsWith(URL, 'data:') then
begin
Fetch(URL, ':');
ContentType := Fetch(URL, ',');
if not TextEndsWith(ContentType, ';base64') then
begin
ShowMessage('Data is not encoded in base64!');
Exit;
end;
SetLength(ContentType, Length(ContentType)-7);
TIdDecoderMIME.DecodeStream(URL, MS);
if ContentType = '' then
ContentType := 'text/plain;charset=US-ASCII';
end else
begin
IdHTTP1 := TIdHTTP.Create;
try
IdHTTP1.IOHandler := TIdSSLIOHandlerSocketOpenSSL.Create(IdHTTP1);
IdHTTP1.HandleRedirects := True;
IdHTTP1.Get(URL, MS);
ContentType := IdHTTP1.Response.ContentType;
finally
IdHTTP1.Free;
end;
end;
MS.Position := 0;
case PosInStrArray(ExtractHeaderItem(ContentType),
['image/gif', 'image/jpeg', 'image/bmp'{, ...}],
False) of
0: Graphic := TGIFImage.Create;
1: Graphic := TJPEGImage.Create;
2: Graphic := TBitmap.Create;
// ...
else
ShowMessage('Unsupported image type!');
Exit;
end;
{ the 'data:' URL you provided is malformed, is says the image type
is 'image/bmp' even though it is actually a GIF and thus should
say 'image/gif'. To avoid problems with the above code determining
the wrong TGraphic class to use in that case, you can instead look
at the first few bytes of the decoded data to determinate its actual
image type, eg...
const
Signature_GIF87a: array[0..5] of Byte = ($47,$49,$46,$38,$37,$61);
Signature_GIF89a: array[0..5] of Byte = ($47,$49,$46,$38,$39,$61);
Signature_JPEG: array[0..2] of Byte = ($FF,$D8,$FF);
Signature_BMP: array[0..1] of Byte = ($42,$4D);
...
if (MS.Size >= 6) and
(CompareMem(MS.Memory, #Signature_GIF87a, 6) or
CompareMem(MS.Memory, #Signature_GIF89a, 6)) then
begin
Graphic := TGIFImage.Create;
end
else if (MS.Size >= 3) and
CompareMem(MS.Memory, #Signature_JPEG, 3) then
begin
Graphic := TJPEGImage.Create;
end
else if (MS.Size >= 2) and
CompareMem(MS.Memory, #Signature_BMP, 2) then
begin
Graphic := TBitmap.Create;
end
...
else
ShowMessage('Unsupported image type!');
Exit;
end;
}
Graphic.LoadFromStream(MS);
finally
MS.Free;
end;
Image1.Picture.Assign(Graphic);
finally
Graphic.Free;
end;
if Image.Picture.Graphic is TGIFImage then
begin
TGIFImage(Image.Picture.Graphic).Animate := True;
//TGIFImage(Image.Picture.Graphic).AnimationSpeed := 500;
end;
end;

How to send a bitmap with HTTP post method

I would like to send a bitmap image with an HTTP POST method. How can I send it to a URL?
I am using Indy 10 and Delphi 10.1. In a procedure, I create a TStringList with all parameter values, but I don't know how to pass the bitmap data.
This is my code:
procedure TuDm_Athlos.AddComandaInsertLogo(workList: TStringList;
imageStream: TStream);
var
image : TBitmap;
begin
try
image := TBitmap.Create;
imageStream := TStream.Create;
image.LoadFromFile('D:\\COFEE.BMP');
image.SaveToStream(imageStream);
workList.Add('db=titles');
workList.Add('line_1=');
worklist.Add('line_2=');
workList.Add('line_3=');
workList.Add('line_4=');
workList.Add('line_5=');
workList.Add('line_6=');
workList.Add('store=&DB=PRN_UDG');
workList.Add('code=1');
workList.Add('width=' + IntToStr(image.Width));
workList.Add('height=' + IntToStr(image.Height));
workList.Add('length=576');
workList.Add('store=');
finally
FreeAndNil(imageStream);
end;
end;
function TuDm_Athlos.InsertLogo(imageStream: TStream;
isFullResponse: Boolean): Boolean;
var
StrResult : UTF8String;
workList : TStringList;
ContentStream : TStream;
image : TBitmap;
begin
//Setup;
Result := False;
try
try
workList := TStringList.Create;
ContentStream := TStream.Create;
image := TBitmap.Create;
image.LoadFromStream(imageStream);
AddComandaInsertLogo(workList,imageStream);
AddComandaSummarize(workList, False);
StrResult := IdHTTP1.Post(printerURL + 'db_status.xml?',workList);
ContentStream := StringToStream(strResult);
Result := XmlReadCommanda(imageStream); //XmlReadComanda(ContentStream);
except
on e : Exception do begin
//DisconnectHttpClient;
//raise Exception.Create(TranslateHttpError(e.Message));
end;
end;
finally
FreeAndNil(workList);
FreeAndNil(image);
ContentStream.Free;
end;
end;
You can send a file or stream using TIdMultiPartFormDataStream instead of TStringList.
uses
..., IdMultipartFormData;
procedure postImage(Url, FileName: String; imageStream: TStream);
var
Form : TIdMultiPartFormDataStream;
LStream: TStream;
begin
if imageStream = nil then
LStream := TIdReadFileExclusiveStream.Create(FileName)
else
LStream := imageStream;
try
Form := TIdMultiPartFormDataStream.Create;
try
Form.AddFormField('db', 'titles');
Form.AddFormField('line_1', '');
Form.AddFormField('line_2', '');
Form.AddFormField('line_3', '');
Form.AddFormField('line_4', '');
Form.AddFormField('line_5', '');
Form.AddFormField('line_6', '');
Form.AddFormField('store', '');
Form.AddFormField('DB', 'PRN_UDG');
Form.AddFormField('code','1');
Form.AddFormField('width', IntToStr(image.Width));
Form.AddFormField('height',IntToStr(image.Height));
Form.AddFormField('length','576');
Form.AddFormField('store','');
//CREATE A FIELD AND SET THE STREAM
Form.AddFormField('bitmap', '', '', LStream, FileName);
IdHTTP1.Post(Url, Form);
finally
Form.Free;
end;
finally
if imageStream = nil then
LStream.Free;
end;
end;
procedure postImage(Url, FileName : String);
begin
postImage(Url, FileName, nil);
end;

Delphi ZLib Compress / Decompress

I've got a minor issue with decompressing using the ZLib unit in Delphi
unit uZCompression;
interface
uses
uCompression;
type
TZZipCompression = class(TInterfacedObject, ICompression)
public
function DoCompression(aContent: TArray<Byte>): TArray<Byte>;
function DoDecompression(aContent: TArray<Byte>): TArray<Byte>;
function GetWindowsBits: Integer; virtual;
end;
TZGZipCompression = class(TZZipCompression)
function GetWindowsBits: Integer; override;
end;
implementation
uses
System.ZLib, System.Classes, uMxKxUtils;
{ TZCompression }
function TZZipCompression.DoCompression(aContent: TArray<Byte>): TArray<Byte>;
var
LContentStream, LOutputStream: TMemoryStream;
LCompressedStream: TZCompressionStream;
begin
LContentStream := ByteArrayToStream(aContent);
LOutputStream := TMemoryStream.Create;
LCompressedStream := TZCompressionStream.Create(LOutputStream, zcDefault, GetWindowsBits);
LCompressedStream.CopyFrom(LContentStream, LContentStream.Size);
LCompressedStream.Free;
Result := StreamToByteArray(LOutputStream);
LOutputStream.Free;
LContentStream.Free;
end;
function TZZipCompression.DoDecompression(aContent: TArray<Byte>): TArray<Byte>;
var
LContentStream, LOutputStream: TMemoryStream;
LDecompressedStream: TZDecompressionStream;
begin
LContentStream := ByteArrayToStream(aContent);
LOutputStream := TMemoryStream.Create;
LDecompressedStream := TZDecompressionStream.Create(LContentStream);
LOutputStream.CopyFrom(LDecompressedStream, LDecompressedStream.Size);
LDecompressedStream.Free;
Result := StreamToByteArray(LOutputStream);
LOutputStream.Free;
LContentStream.Free;
end;
function TZZipCompression.GetWindowsBits: Integer;
begin
Result := 15;
end;
{ TZGZipCompression }
function TZGZipCompression.GetWindowsBits: Integer;
begin
Result := inherited;
Result := Result + 16;
end;
end.
This is my unit which is driven by an interface (which you don't need to know about), and data is passed in and out through a TArray variables.
I've coded it to be able to do 2 types of compression, standard zip and gzip which is determined by the windowsbits passed in to the functions.
Here are a couple of other functions being used to convert the TArray to TMemoryStream
function ByteArrayToStream(aContent: TArray<Byte>): TMemoryStream;
begin
Result := TMemoryStream.Create;
Result.Write(aContent, length(aContent)*SizeOf(aContent[0]));
Result.Position := 0;
end;
function StreamToByteArray(aStream: TMemoryStream): TArray<Byte>;
var
LStreamPos: Int64;
begin
if Assigned(aStream) then
begin
LStreamPos := aStream.Position;
aStream.Position := 0;
SetLength(Result, aStream.Size);
aStream.Read(Result, aStream.Size);
aStream.Position := LStreamPos;
end
else
SetLength(Result, 0);
end;
Now I can compress and decompress to .zip using the TZZipCompression class perfectly fine (it doesn't open up as a zip file, but it does decompress back to the original file which I can open and edit).
I can also compress to .gz using the TZGZipCompression class fine as well (interestingly I can open this gzip file perfectly well).
My issue however is that it won't decompress back from the .gz file and throws and error as soon as it hits
LOutputStream.CopyFrom(LDecompressedStream, LDecompressedStream.Size)
Funnily enough the Help file example has it as below
LOutputStream.CopyFrom(LDecompressedStream, 0)
But this doesn't work either.
Can anyone spot the issue?
Your conversion functions between TArray<Byte> and TMemoryStream are wrong, as you are not accessing the array content correctly. TArray is a dynamic array. When calling TMemoryStream.Write() and TMemoryStream.Read(), you are passing the memory address of the TArray itself, not the memory address of the data that the TArray points at. You need to reference the TArray to get the correct memory address, eg:
function ByteArrayToStream(const aContent: TArray<Byte>): TMemoryStream;
begin
Result := TMemoryStream.Create;
try
if Length(aContent) > 0 then
Result.WriteBuffer(aContent[0], Length(aContent));
Result.Position := 0;
except
Result.Free;
raise;
end;
end;
function StreamToByteArray(aStream: TMemoryStream): TArray<Byte>;
begin
if Assigned(aStream) then
begin
SetLength(Result, aStream.Size);
if Length(Result) > 0 then
Move(aStream.Memory^, Result[0], aStream.Size);
end
else
SetLength(Result, 0);
end;
Alternatively:
function ByteArrayToStream(const aContent: TArray<Byte>): TMemoryStream;
begin
Result := TMemoryStream.Create;
try
Result.WriteBuffer(PByte(aContent)^, Length(aContent));
Result.Position := 0;
except
Result.Free;
raise;
end;
end;
function StreamToByteArray(aStream: TMemoryStream): TArray<Byte>;
begin
if Assigned(aStream) then
begin
SetLength(Result, aStream.Size);
Move(aStream.Memory^, PByte(Result)^, aStream.Size);
end
else
SetLength(Result, 0);
end;
That being said, you don't need to waste memory making copies of the array data using TMemoryStream. You can use TBytesStream instead (since dynamic arrays are reference counted), eg:
function TZZipCompression.DoCompression(aContent: TArray<Byte>): TArray<Byte>;
var
LContentStream, LOutputStream: TBytesStream;
LCompressedStream: TZCompressionStream;
begin
LContentStream := TBytesStream.Create(aContent);
try
LOutputStream := TBytesStream.Create(nil);
try
LCompressedStream := TZCompressionStream.Create(LOutputStream, zcDefault, GetWindowsBits);
try
LCompressedStream.CopyFrom(LContentStream, 0);
finally
LCompressedStream.Free;
end;
Result := Copy(LOutputStream.Bytes, 0, LOutputStream.Size);
finally
LOutputStream.Free;
end;
finally
LContentStream.Free;
end;
end;
function TZZipCompression.DoDecompression(aContent: TArray<Byte>): TArray<Byte>;
var
LContentStream, LOutputStream: TBytesStream;
LDecompressedStream: TZDecompressionStream;
begin
LContentStream := TBytesStream.Create(aContent);
try
LOutputStream := TBytesStream.Create(nil);
try
LDecompressedStream := TZDecompressionStream.Create(LContentStream, GetWindowsBits);
try
LOutputStream.CopyFrom(LDecompressedStream, 0);
finally
LDecompressedStream.Free;
end;
Result := Copy(LOutputStream.Bytes, 0, LOutputStream.Size);
finally
LOutputStream.Free;
end;
finally
LContentStream.Free;
end;
end;

How to get image binary data using XMLHTTPRequest in Delphi

I need to access binary image data using XMLHttpRequest in Delphi. I am using the following code but its not working, could someone please tell me what's wrong with this code, thanks in advance.
//I am using this function to get Image Binary data into Memory Stream.
procedure SendGETRequest(p_Url: string; p_resStream: TMemoryStream);
begin
FXmlHttpReq.open(METHOD_GET, p_Url, false, FUsername, FPassword);
FXmlHttpReq.setRequestHeader(HTTP_AUTHENTICATION, HTTP_BASIC + EncodeBase64(
FUsername + ':'+FPassword));
FXmlHttpReq.setRequestHeader(HTTP_CACHE_CONTROL, HTTP_NO_CACHE);
//FXmlHttpReq.setRequestHeader('Content-type','application/octet-stream');
FXmlHttpReq.send('');
if not VarIsEmpty(FXmlHttpReq.responseBody) then
begin
p_resStream:= OleVariantToMemoryStream(FXmlHttpReq.responseStream);
end;//if...
end;
function OleVariantToMemoryStream(OV: OleVariant): TMemoryStream;
var
Data: PByteArray;
Size: integer;
begin
Result := TMemoryStream.Create;
try
Size := VarArrayHighBound (OV, 1) - VarArrayLowBound(OV, 1) + 1;
Data := VarArrayLock(OV);
try
Result.Position := 0;
Result.WriteBuffer(Data^, Size);
finally
VarArrayUnlock(OV);
end;
except
Result.Free;
Result := nil;
end;
end;
responseStream is IStream. You need to convert it using TOleStream (AxCtrls):
uses AxCtrls, ComObj, ActiveX;
procedure TForm1.Button1Click(Sender: TObject);
var
oXMLHTTP: OleVariant;
MemoryStream: TMemoryStream;
Stream: IStream;
OleStream: TOleStream;
begin
oXMLHTTP := CreateOleObject('MSXML2.XMLHTTP.3.0');
oXMLHTTP.open('GET', 'https://www.google.com/images/srpr/logo11w.png', False);
oXMLHTTP.send(EmptyParam);
Stream := IUnknown(oXMLHTTP.ResponseStream) as IStream;
OleStream := TOleStream.Create(Stream);
try
OleStream.Position := 0;
MemoryStream := TMemoryStream.Create;
try
MemoryStream.CopyFrom(OleStream, OleStream.Size);
MemoryStream.SaveToFile('logo11w.png');
finally
MemoryStream.Free;
end;
finally
OleStream.Free;
end;
end;

Posting Data with Indy and Receiving it to TWebBrowser

I am trying to post data to bing with this code
function PostExample: string;
var
lHTTP: TIdHTTP;
lParamList: TStringList;
begin
lParamList := TStringList.Create;
lParamList.Add('q=test');
lHTTP := TIdHTTP.Create(nil);
try
Result := lHTTP.Post('http://www.bing.com/', lParamList);
finally
FreeAndNil(lHTTP);
FreeAndNil(lParamList);
end;
end;
And then, how can I get the result to the TWebBrowser and display it?
Try LoadDocFromString:
procedure LoadBlankDoc(ABrowser: TWebBrowser);
begin
ABrowser.Navigate('about:blank');
while ABrowser.ReadyState <> READYSTATE_COMPLETE do
begin
Application.ProcessMessages;
Sleep(0);
end;
end;
procedure CheckDocReady(ABrowser: TWebBrowser);
begin
if not Assigned(ABrowser.Document) then
LoadBlankDoc(ABrowser);
end;
procedure LoadDocFromString(ABrowser: TWebBrowser; const HTMLString: wideString);
var
v: OleVariant;
HTMLDocument: IHTMLDocument2;
begin
CheckDocReady(ABrowser);
HTMLDocument := ABrowser.Document as IHTMLDocument2;
v := VarArrayCreate([0, 0], varVariant);
v[0] := HTMLString;
HTMLDocument.Write(PSafeArray(TVarData(v).VArray));
HTMLDocument.Close;
end;
Or you can use the memory streams for loading
uses
OleCtrls, SHDocVw, IdHTTP, ActiveX;
function PostRequest(const AURL: string; const AParams: TStringList;
const AWebBrowser: TWebBrowser): Boolean;
var
IdHTTP: TIdHTTP;
Response: TMemoryStream;
begin
Result := True;
try
AWebBrowser.Navigate('about:blank');
while AWebBrowser.ReadyState < READYSTATE_COMPLETE do
Application.ProcessMessages;
Response := TMemoryStream.Create;
try
IdHTTP := TIdHTTP.Create(nil);
try
IdHTTP.Post(AURL, AParams, Response);
if Response.Size > 0 then
begin
Response.Position := 0;
(AWebBrowser.Document as IPersistStreamInit).Load(
TStreamAdapter.Create(Response, soReference));
end;
finally
IdHTTP.Free;
end;
finally
Response.Free;
end;
except
Result := False;
end;
end;
procedure TForm1.Button1Click(Sender: TObject);
var
Params: TStringList;
begin
Params := TStringList.Create;
try
Params.Add('q=test');
if not PostRequest('http://www.bing.com/', Params, WebBrowser1) then
ShowMessage('An unexpected error occured!');
finally
Params.Free;
end;
end;

Resources