How to Get Images From Server using App Tethering

前端 未结 1 1671
隐瞒了意图╮
隐瞒了意图╮ 2020-12-22 06:40

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], SQLi

相关标签:
1条回答
  • 2020-12-22 07:08

    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.

    0 讨论(0)
提交回复
热议问题