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

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;

Related

how to convert idhttp downloaded image from extention to another?

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.

Login OK to site with TwebBrowser , but not with TidHTTP

May I ask for a little help using Indy to login to a website please?
Firstly, just as a 'proof of concept' I used a TWebBrowser to test my credentials in the following manner ...
procedure TfrmMain.cxButton1Click(Sender: TObject);
begin
webBrow.Navigate('http://assurance.redtractor.org.uk/rtassurance/services.eb');
end;
procedure TfrmMain.webBrowDocumentComplete(ASender: TObject;
const pDisp: IDispatch; var URL: OleVariant);
var
CurrentBrowser: IWebBrowser2;
TopBrowser: IWebBrowser2;
Document: OleVariant;
Doc3 : IHTMLDocument3;
Frm : IHtmlFormElement;
begin
CurrentBrowser := pDisp as IWebBrowser2;
TopBrowser := (ASender as TWebbrowser).DefaultInterface;
if Assigned(CurrentBrowser) and Assigned(TopBrowser) then
begin
if CurrentBrowser = TopBrowser then
begin
Doc3 := CurrentBrowser.Document as IHTMLDocument3;
Webbrow.OnDocumentComplete := nil; // remove handler to avoid reentrance
Doc3.getElementById('el9M9AQXIL51JI3_loginPnl_username').setAttribute('value', 'aValidUserName', 0);
Doc3.getElementById('el9M9AQXIL51JI3_loginPnl_password').setAttribute('value', 'aValidPassword', 0);
//Frm := Doc3.getElementById('ct100') as IHtmlFormElement;
Doc3.GetElementByID('el9M9AQXIL51JI3_loginPnl_button').click();
end;
end;
end;
I got the above from the whosrdaddy answer here Automated Log In (webBrowser)
That logs me into the site and takes me to a search page ... exactly what I need.
However, I'd like to avoid using a TWebBrowser as I thought my searches would be slow due to the fact the page would need to be rendered.
With that in mind I tried to use Indy 10 to login to the same address, passing the parameters like so ...
idRedTractor.Post(login_URL, Request, Response);
But all this returns is a 'Server Error, Unauthenticated UserName' response.
My full code for trying to login is ...
procedure TfrmMain.btnLogonClick(Sender: TObject);
var
Response : TMemoryStream;
searchResp : TMemoryStream;
Request : TStringList;
searchReq : TStringList;
resultStr : TStringList;
begin
with IdRedTractor do
begin
allowCookies := true;
cookieManager := cookieRedTractor;
IOhandler := IdSSLRedTractor;
request.Accept := 'text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8';
request.contentType := 'text/html';
request.userAgent := 'Mozilla/3.0 (compatible; Indy Library)';
end;
with IdSSLRedTractor do
begin
// SSLOptions does not make a difference. Still get a Server Error message
SSLOptions.Mode := sslmUnassigned;
//SSLOptions.Mode := sslmBoth;
//SSLOptions.Mode := sslmClient;
//SSLOptions.Mode := sslmServer;
end;
try
try
response := TMemoryStream.Create;
searchResp := TMemoryStream.Create;
try
request := TStringList.Create;
searchReq := TStringList.Create;
resultStr := TStringList.Create;
// Individual params via FireBug
Request.Add('__EVENTARGUMENT=login');
Request.Add('__EVENTTARGET=el9M9AQXIL51JI3$loginPnl');
Request.Add('__VIEWSTATE=/wEPDwULLTEzMjc3NzQ0ODEPZBYEAgEPZBYCZg9kFgJmDxYCHgRUZXh0BRNDaGVja2VycyAmIFNlcnZpY2VzZAIDD2QWBAICDxYCHgdWaXNpYmxlaGQCCQ9kFgICAg9kFgICBA8WAh8BZxYCAgEPFgIfAWhkZD3T1Ydwd12+6SzZOgVHrnka9LKB');
Request.Add('__VIEWSTATEGENERATOR=9D5BCA8C');
Request.Add('ebAbPwd=' + edtUserPass.text);
Request.Add('ebAbPwd=');
Request.Add('ebAbUser=' + edtUserName.text);
Request.Add('ebAbUser=');
Request.Add('el9M9AQXIL51JI3$loginPnl_...=' + edtUserName.Text);
Request.Add('el9M9AQXIL51JI3$loginPnl_...=' + edtUserPass.text);
Request.Add('el9OK3XX11WQS60_email=');{}
IdRedTractor.Request.Referer := 'http://assurance.redtractor.org.uk/rtassurance/schemes.eb';//initial_URL;
IdRedTractor.Post('http://assurance.redtractor.org.uk/rtassurance/services.eb', Request, Response);
if idRedtractor.ResponseCode = 200 then
begin
resultStr.Clear;
Response.Position := 0;
resultStr.LoadFromStream(Response);
mmoResponse.Lines.AddStrings(resultStr);
end;
finally
request.Free;
searchReq.Free;
resultStr.Free;
end;
finally
response.Free;
searchResp.Free;
end;
except
on e: Exception do
showMessage(e.Message);
end;
end;
Just is case there is some value in the versions of the SSL DLL's, they are 'libeay32.dll' v1.0.1.3 and 'ssleay32.dll', also v1.0.1.3.
May I ask for your help please in understanding what I have missed or done wrong that prevents me from logging into this site with a TidHTTP?
Ok, found your problem.
The site is doing a redirect to the same page after the POST login request.
The key to the solution is setting HandleRedirects to True and change the VMethod variable to GET in the OnHandleRedirect event. I cleaned up the code a bit:
unit SO35263785Test;
interface
uses
IdHttp,
SysUtils,
StrUtils,
StdCtrls,
Classes,
Controls,
Forms;
type
TForm1 = class(TForm)
Memo1: TMemo;
Button1: TButton;
procedure Button1Click(Sender: TObject);
private
{ Private declarations }
Client : TIdHttp;
procedure HandleRedirect(Sender: TObject; var dest: string; var NumRedirect: Integer; var Handled: boolean; var VMethod: TIdHTTPMethod);
procedure LoginToRedTractor(const Username, Password : String);
public
{ Public declarations }
end;
var
Form1: TForm1;
implementation
{$R *.dfm}
procedure TForm1.HandleRedirect(Sender: TObject; var dest: string; var NumRedirect: Integer; var Handled: boolean; var VMethod: TIdHTTPMethod);
begin
VMethod := Id_HTTPMethodGet;
Handled := True;
end;
procedure ExtractViewStateAndGenerator(const Html : String; var ViewState : String; var ViewStateGenerator: String);
var
Ps : Integer;
begin
ViewState := '';
ViewStateGenerator := '';
// we assume __VIEWSTATE and __VIEWSTATEGENERATOR inputs are there, NO error checking
Ps := Pos('__VIEWSTATE', Html);
Ps := PosEx('value', Html, Ps);
Ps := PosEx('"', Html, Ps);
ViewState := Copy(Html, Ps+1, PosEx('"', Html, Ps+1)-Ps-1);
Ps := Pos('__VIEWSTATEGENERATOR', Html);
Ps := PosEx('value', Html, Ps);
Ps := PosEx('"', Html, Ps);
ViewStateGenerator := Copy(Html, Ps+1, PosEx('"', Html, Ps+1)-Ps-1);
end;
procedure TForm1.LoginToRedTractor(const Username, Password : String);
var
GETResponse : String;
Request : TStringList;
ViewState : String;
ViewStateGenerator : String;
begin
Client := TIdHttp.Create;
try
Client.ProtocolVersion := pv1_1;
Client.HTTPOptions := [hoForceEncodeParams, hoKeepOrigProtocol];
Client.AllowCookies := True;
Client.HandleRedirects := True;
Client.Request.UserAgent := 'Mozilla/5.0 (Windows NT 6.3; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/48.0.2564.103 Safari/537.36';
Client.OnRedirect := HandleRedirect;
GETResponse := Client.Get('http://assurance.redtractor.org.uk/rtassurance/schemes.eb');
ExtractViewStateAndGenerator(GETResponse, ViewState, ViewStateGenerator);
Request := TStringList.Create;
try
Request.Add('__VIEWSTATE='+ViewState);
Request.Add('__VIEWSTATEGENERATOR='+ViewStateGenerator);
Request.Add('__EVENTTARGET=el9M9AQXIL51JI3$loginPnl');
Request.Add('el9M9AQXIL51JI3$loginPnl_username='+Username);
Request.Add('el9M9AQXIL51JI3$loginPnl_password='+Password);
Client.Request.Referer := Client.URL.URI;
Memo1.Text := Client.Post('http://assurance.redtractor.org.uk/rtassurance/services.eb', Request);
finally
Request.Free;
end;
finally
Client.Free;
end;
end;
procedure TForm1.Button1Click(Sender: TObject);
begin
LoginToRedTractor('MyUsername', 'MyPassword');
end;
end
This code has been verified and works in Delphi XE.

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;

delphi, send image with indy10 from client to server

How I can send from a Timage (clientside) to another Timage(serverside)?
I'm using delphi XE3 with idtcpclient1, idtcpserver1 (indy10 component).
I already tried to do something but I had some trouble.
Server side:
FileStream := TFileStream.Create('ciao.jpg', fmCreate);
AContext.Connection.IOHandler.LargeStream := True;
AContext.Connection.IOHandler.ReadStream(FileStream); FileStream.Free;
image1.Picture.LoadFromFile(sname);
Client side:
idTCPClient1.IOHandler.LargeStream := True;
FileStream := TFileStream.Create('hello.jpg', fmOpenRead);
IdTCPClient1.IOHandler.Write(FileStream,0,true);
filestream.Free;
Example implementation for the transfer of different graphic formats.
Main issue is that you will have to create an appropriate GraphicClass.
If an image is loaded from a file the class is determinate from the file extension.
In this implemetation we add the information to the stream.
unit Unit1;
interface
uses
Winapi.Windows, Winapi.Messages, System.SysUtils, System.Variants, System.Classes, Vcl.Graphics,
Vcl.Controls, Vcl.Forms, Vcl.Dialogs, IdContext, Vcl.ExtCtrls, IdTCPConnection, IdTCPClient, IdBaseComponent,
IdComponent, IdCustomTCPServer, IdTCPServer, Vcl.StdCtrls, Vcl.Imaging.jpeg;
type
TForm1 = class(TForm)
IdTCPServer1: TIdTCPServer;
IdTCPClient1: TIdTCPClient;
Source: TImage;
Dest: TImage;
Button1: TButton;
procedure FormCreate(Sender: TObject);
procedure IdTCPServer1Execute(AContext: TIdContext);
procedure Button1Click(Sender: TObject);
private
{ Private-Deklarationen }
public
{ Public-Deklarationen }
end;
var
Form1: TForm1;
implementation
uses PNGImage;
{$R *.dfm}
//Enable transfer of different graphicformats
procedure Picture2Stream(DestStream: TMemoryStream; Picture: TPicture);
var
ms2: TMemoryStream;
TheClassName: AnsiString;
len: Byte;
begin
TheClassName := Picture.Graphic.ClassName;
len := Length(TheClassName);
DestStream.WriteBuffer(len, 1);
if len > 0 then // save GraphicClass name
DestStream.WriteBuffer(TheClassName[1], len);
ms2 := TMemoryStream.Create;
try // save graphic
Picture.Graphic.SaveToStream(ms2);
ms2.Position := 0;
if ms2.Size > 0 then
DestStream.CopyFrom(ms2, ms2.Size);
finally
ms2.Free;
end;
end;
Procedure LoadPictureFromStream(Picture: TPicture; SourceStream: TMemoryStream);
var
ms2: TMemoryStream;
len: Byte;
TheClassName: AnsiString;
Graphic: TGraphic;
GraphicClass: TGraphicClass;
begin
SourceStream.Position := 0;
SourceStream.ReadBuffer(len, 1);
SetLength(TheClassName, len);
if len > 0 then // read GraphicClass name
SourceStream.ReadBuffer(TheClassName[1], len);
GraphicClass := TGraphicClass(FindClass(TheClassName)); //(*)
if (GraphicClass <> nil) and (len > 0) then
begin
Graphic := GraphicClass.Create; // create appropriate graphic class
try
ms2 := TMemoryStream.Create;
try
ms2.CopyFrom(SourceStream, SourceStream.Size - len - 1);
ms2.Position := 0;
Graphic.LoadFromStream(ms2);
finally
ms2.Free;
end;
Picture.Assign(Graphic);
finally
Graphic.Free;
end;
end;
end;
procedure TForm1.Button1Click(Sender: TObject);
var
ms: TMemoryStream;
begin
ms := TMemoryStream.Create;
try
Picture2Stream(ms, Source.Picture);
ms.Position := 0;
IdTCPClient1.Host := '127.0.0.1';
IdTCPClient1.Port := 12345;
IdTCPClient1.Connect;
IdTCPClient1.IOHandler.LargeStream := true;
IdTCPClient1.IOHandler.Write(ms, ms.Size, true);
finally
ms.Free;
end;
end;
procedure TForm1.FormCreate(Sender: TObject);
begin
IdTCPServer1.DefaultPort := 12345;
IdTCPServer1.Active := true;
ReportMemoryLeaksOnShutDown := true;
end;
procedure TForm1.IdTCPServer1Execute(AContext: TIdContext);
var
ms: TMemoryStream;
begin
ms := TMemoryStream.Create;
try
AContext.Connection.IOHandler.LargeStream := true;
AContext.Connection.IOHandler.ReadStream(ms);
TThread.Synchronize(nil,
Procedure
begin
LoadPictureFromStream(Dest.Picture, ms);
end);
finally
ms.Free;
end;
end;
initialization
// RegisterClasses to enable FindClass (*)
RegisterClasses([TIcon, TMetafile, TBitmap, TJPEGImage, TPngImage]);
end.
Your question is unclear, but it seems that you're trying to transfer the content of one 'TImage' (on the client) to a TImage on the server. It's unclear whether you mean an image file or an actual TImage, though. I'm going to go with "the picture being displayed in a TImage on the client" being sent to the server.
You can use TMemoryStream instead of TFileStream. If you really mean to send the image displayed in a TImage.Picture, you can do something like this (untested):
// Server side
var
Jpg: TJpegImage;
begin
Strm := TMemoryStream.Create;
try
Strm.Position := 0;
AContext.Connection.IOHandler.LargeStream := True;
AContext.Connection.IOHandler.ReadStream(Strm);
Strm.Position := 0;
Jpg := TJpegImage.Create;
try
Jpg.LoadFromStream(Strm);
Image1.Picture.Assign(Jpg);
finally
Jpg.Free;
end;
finally
Strm.Free;
end;
end;
// Client side
IdTCPClient1.IOHandler.LargeStream := True;
Strm := TMemoryStream.Create;
try
Image1.Picture.Graphic.SaveToStream(Strm);
Strm.Position := 0;
IdTCPClient1.IOHandler.Write(Strm, 0, True);
finally
Strm.Free;
end;
If that's not what you want, edit your question so we can understand what you're trying to do. (Don't tell us in comments, but actually edit your question to make it more clear.)

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