0

I've 2 Apps Let's call Server And Client.

I'm using Delphi-xe8. App ->Multi-Device Application

In Both Side using: App tethering[tManager,tAProfile], SQLite Database.

In Server SQLite Database I've 6 images. I would like to View that images In Client Side.

In Client Side I've 6 [TImage].

When I Click Button 'Get Image List' I'm getting 6 images with the same view.

I would like 6 images view differently.->[Get From Server Database]

Client Side

Client "Get Image List" button Code:

procedure TForm1.GetImgLstClick(Sender: TObject);
begin
  tAProfile.SendString(tManager.RemoteProfiles.First,'GetImages','');
end;

Server Received Code:

procedure TForm2.tAProfileResourceReceived(const Sender: TObject;
  const AResource: TRemoteResource);
  var
    MS1:TMemorystream;
begin

     if AResource.Hint='GetImages' then
       begin
        MS1:=TMemorystream.Create;

         rQuery.Close;
         rQuery.SQL.Clear;
         rQuery.SQL.Add('select image from users');
         rQuery.Open;
         while not rQuery.Eof do
          begin
            tblobField(rQuery.FieldByName('image')).SaveToStream(MS1);
            Image1.Bitmap:=nil;
            rQuery.Next;
          end; 
      tAProfile.SendStream(tManager.RemoteProfiles.First,'SendImages',MS1);
       end;
end;

Client Received Code:

procedure TForm1.tAProfileResourceReceived(const Sender: TObject;
  const AResource: TRemoteResource);
 var
  MS:TMemoryStream;
begin
 if AResource.Hint='SendImages' then
    begin
      Image1.Bitmap.LoadFromStream(AResource.Value.AsStream);
      Image2.Bitmap.LoadFromStream(AResource.Value.AsStream);
      Image3.Bitmap.LoadFromStream(AResource.Value.AsStream);
      Image4.Bitmap.LoadFromStream(AResource.Value.AsStream);
      Image5.Bitmap.LoadFromStream(AResource.Value.AsStream);
      Image6.Bitmap.LoadFromStream(AResource.Value.AsStream);
    end;
end;
Tom Brunberg
  • 20,312
  • 8
  • 37
  • 54
Alex Kirov
  • 217
  • 4
  • 16
  • I'm using Delphi-xe8. App ->Multi-Device Application – Alex Kirov Feb 10 '17 at 07:20
  • The screenshots are irrelevant to this and your question yesterday which asked the same thing. What dataset type are you using in your server app? – MartynA Feb 10 '17 at 07:34
  • @TomBrunberg: I've already shown the OP how to do this in my answer to his q yesterday:http://stackoverflow.com/questions/42140246/delphi-how-to-get-all-images-from-server-database-by-using-app-tethering/42144117#42144117. The step he seems to be missing is how to get the data from his Sqlite db into a ClientDataSet, which I'll explain in a moment. – MartynA Feb 10 '17 at 07:37
  • @MartynA Ok, you are much, much better at the db stuff ;) – Tom Brunberg Feb 10 '17 at 07:57
  • Possible duplicate of [Delphi: How to Get All Images From Server Database by using App tethering?](http://stackoverflow.com/questions/42140246/delphi-how-to-get-all-images-from-server-database-by-using-app-tethering) – MartynA Feb 10 '17 at 08:26

1 Answers1

2

Update: I gather from your most recent comment that you want to send your images one-by-one.

A problem is that a Delphi dataset's TGraphicField supports a number of formats which may be of variable size, so if you just write them to the server's outbound stream, there is no way for the client to know, when reading the stream, where the data of one image ends and the next one begins. A simple solution to that is to have the server write the size of the image to the stream before it writes the image's data to the stream, and get the client's code to read the image size so that it knows how much of what follows is the image's data.

I'm going back to the answer I posted to your other q (Delphi: How to Get All Images From Server Database by using App tethering?), which uses TClientDataSets, but adapting it so that it sends only the images (and their sizes) in the stream. The code is still quite simple and should be no different in principle than using FireDAC datasets and a Sqlite data table:

Server

procedure TApp1Form.SendImageStream;
var
  StreamToSend,
  ImageStream : TMemoryStream;
  StreamedImageSize : Integer;
begin
  StreamToSend := TMemoryStream.Create;
  ImageStream := TMemoryStream.Create;
  try
    CDS1.DisableControls;
    CDS1.First;
    while not CDS1.Eof do begin
      ImageStream.Clear;
      CDS1Graphic.SaveToStream(ImageStream);
      ImageStream.Position := 0;
      StreamedImageSize := ImageStream.Size;
      StreamToSend.Write(StreamedImageSize, SizeOf(Integer));
      StreamToSend.CopyFrom(ImageStream, StreamedImageSize);
      CDS1.Next;
    end;
    StreamToSend.Position := 0;
    TetheringAppProfile1.Resources.FindByName('BioLife').Value := StreamToSend;
  finally
    CDS1.EnableControls;
    ImageStream.Free;
  end;
end;

Client

//  Note: In the client, CDS1 has only two fields, one named ID which is an
//  ftAutoInc field, and Graphic, which is a TGraphicField

procedure TApp2Form.TetheringAppProfile1Resources0ResourceReceived(const Sender:
    TObject; const AResource: TRemoteResource);
var
  ReceivedStream : TStream;
  ImageStream : TMemoryStream;
  ImageSize : Integer;
begin
  AResource.Value.AsStream.Position := 0;

  ReceivedStream := AResource.Value.AsStream;
  ImageStream := TMemoryStream.Create;
  try
    if CDS1.Active then
      CDS1.EmptyDataSet  // discard existing data
    else
      CDS1.CreateDataSet;
    CDS1.DisableControls;
    while ReceivedStream.Position < ReceivedStream.Size - 1 do begin
      ImageStream.Clear;
      ReceivedStream.ReadBuffer(ImageSize, SizeOf(Integer));
      ImageStream.CopyFrom(ReceivedStream, ImageSize);
      CDS1.Insert;
      TGraphicField(CDS1.FieldByName('Graphic')).LoadFromStream(ImageStream);
      CDS1.Post;
    end;
    CDS1.First;
  finally
    ImageStream.Free;
    CDS1.EnableControls;
  end;
end;

Original answer follows

I have already shown you a very simple way to move images between server and client app using TClientDataSets in my answer to your q Delphi: How to Get All Images From Server Database by using App tethering?. I assumed you knew enough about Delphi programming to be able to get the data from your Sqlite db into a TCientDataSet but perhaps not.

Below is the code for the server + client of my other answer, adapted to use FireDAC components instead of TClientDataSets. Again, it uses the server dataset's SaveToStream method to save its data to the stream from the server and LoadFromStream on the client side.

Notice that there are only two lines of code in the client app.

FDApp1 code:

type
  TApp1Form = class(TForm)
    TetheringManager1: TTetheringManager;
    TetheringAppProfile1: TTetheringAppProfile;
    DBImage1: TDBImage;
    btnConnect: TButton;
    Label1: TLabel;
    DataSource1: TDataSource;
    DBGrid1: TDBGrid;
    DBNavigator1: TDBNavigator;
    btnSendStream: TButton;
    FDConnection1: TFDConnection;
    FDQuery1: TFDQuery;
    FDGUIxWaitCursor1: TFDGUIxWaitCursor;
    FDStanStorageBinLink1: TFDStanStorageBinLink;
    procedure btnConnectClick(Sender: TObject);
    procedure btnSendStreamClick(Sender: TObject);
    procedure FormCreate(Sender: TObject);
    procedure TetheringManager1PairedToRemote(const Sender: TObject; const
        AManagerInfo: TTetheringManagerInfo);
  private
    procedure DataSetToStream;
  end;

[...]

procedure TApp1Form.btnConnectClick(Sender: TObject);
begin
  TetheringManager1.AutoConnect;
end;

procedure TApp1Form.btnSendStreamClick(Sender: TObject);
begin
  DataSetToStream;
end;

procedure TApp1Form.FormCreate(Sender: TObject);
begin
  Caption := Format('App1 : %s', [TetheringManager1.Identifier]);
  FDQuery1.LoadFromFile('D:\D10\Samples\Data\BioLife.FDS');
end;

procedure TApp1Form.TetheringManager1PairedToRemote(const Sender: TObject; const
    AManagerInfo: TTetheringManagerInfo);
begin
  Label1.Caption := Format('Connected : %s %s',
                         [AManagerInfo.ManagerIdentifier,
                          AManagerInfo.ManagerName]);
end;

procedure TApp1Form.DataSetToStream;
var
  Stream : TMemoryStream;
begin
  Stream := TMemoryStream.Create;
  FDQuery1.SaveToStream(Stream);
  Stream.Position := 0;
  TetheringAppProfile1.Resources.FindByName('BioLife').Value := Stream;
end;

FDApp2 code:

type
  TApp2Form = class(TForm)
    TetheringManager1: TTetheringManager;
    TetheringAppProfile1: TTetheringAppProfile;
    DataSource1: TDataSource;
    DBGrid1: TDBGrid;
    DBNavigator1: TDBNavigator;
    DBImage1: TDBImage;
    FDGUIxWaitCursor1: TFDGUIxWaitCursor;
    FDMemTable1: TFDMemTable;
    FDStanStorageBinLink1: TFDStanStorageBinLink;
    procedure TetheringAppProfile1Resources0ResourceReceived(const Sender: TObject;
        const AResource: TRemoteResource);
  public
  end;

[...]
procedure TApp2Form.TetheringAppProfile1Resources0ResourceReceived(const Sender:
    TObject; const AResource: TRemoteResource);
begin
  AResource.Value.AsStream.Position := 0;
  FDMemTable1.LoadFromStream(AResource.Value.AsStream);
end;

Of course, on the client side, if for some reason you want the images (but not the other server data) copied into another dataset, you can do that by a row-by-row copy, similar to the code in your qs.

Community
  • 1
  • 1
MartynA
  • 30,454
  • 4
  • 32
  • 73
  • Dataset Type: rQuery: TFDQuery – Alex Kirov Feb 10 '17 at 08:29
  • @AlexKirov: I've added a full FireDAC Server + Client to my answer. – MartynA Feb 10 '17 at 09:46
  • this is not what I want. I need to split From Server MS1 and From Client AResource.Value.AsStream) – Alex Kirov Feb 10 '17 at 11:26
  • @AlexKirov:"I need to split From Server MS1 and From Client AResource.Value.AsStream" What does that mean? You seem to be assuming that you can just write images to a stream one after the other. Why persist with trying to do that when there is a much easier way? – MartynA Feb 10 '17 at 11:49
  • I tried , not working. as an example: http://stackoverflow.com/questions/42056070/how-to-split-string-by-splitstring-or-delimiter but I need Split Steam I don't know how? – Alex Kirov Feb 10 '17 at 12:03
  • @AlexKirov: Ok, I've changed my answer to show you what you need to do in the server and client so that you cam split the stream in the client. – MartynA Feb 10 '17 at 12:56
  • @AlexKirov: Has my update answered about "splitting"? – MartynA Feb 10 '17 at 14:56
  • @ MartynA Thank you all for answer but I am still unable to verify. – Alex Kirov Feb 12 '17 at 10:07