如何使用应用程序捆绑从服务器获取图像 [英] How to Get Images From Server using App Tethering

查看:205
本文介绍了如何使用应用程序捆绑从服务器获取图像的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我有2个应用程序让我们打电话给服务器和客户端。



我使用的是Delphi-xe8。应用程序 - >多设备应用程序



在双方使用:应用程序绑定[tManager,tAProfile],SQLite数据库。



在服务器SQLite数据库中我有6张图像。我想在客户端查看图像。



在客户端我有6 [TImage]。



当我点击按钮获取图像列表我有6个图像具有相同的视图。



我想要6张图像视图不同.-> [从服务器数据库获取]





客户端获取图像列表按钮代码: p>

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

收到的服务器代码

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

如果AResource.Hint ='GetImages'然后
begin
MS1:= TMemorystream.Create;

rQuery.Close;
rQuery.SQL.Clear;
rQuery.SQL.Add('select image from users');
rQuery.Open;
而不是rQuery.Eof do
begin
tblobField(rQuery.FieldByName('image'))。SaveToStream(MS1);
Image1.Bitmap:= nil;
rQuery.Next;
结束
tAProfile.SendStream(tManager.RemoteProfiles.First,'SendImages',MS1);
结束
结束

收到的客户端代码

  procedure TForm1.tAProfileResourceReceived(const Sender:TObject; 
const AResource:TRemoteResource);
var
MS:TMemoryStream;
begin
如果AResource.Hint ='SendImages'然后
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);
结束
结束


解决方案

更新:从您最近的评论中,您要一个一个地发送
图像。



一个问题是,Delphi数据集的TGraphicField支持多种格式
可能是可变大小的,所以如果你只是将它们写入服务器的出站
流,那么在读取流时,客户端无法知道
数据的位置一个图像结束,下一个图像开始。一个简单的解决方案是在
之前,服务器将图像的大小写入流,然后将图像的
数据写入流,并获取客户端的代码来读取图像大小,以便它
知道图像的数据有多少。



我要回到我发布给你其他q的答案(德尔菲:如何获取所有图片从服务器数据库通过使用应用程序绑定?),它使用TClientDataSets
,但适应它,以便它只在流中发送图像(及其大小)。
代码仍然相当简单,原则上与使用FireDAC数据集和Sqlite数据表相比应该没有什么不同:



服务器

 程序TApp1Form.SendImageStream; 
var
StreamToSend,
ImageStream:TMemoryStream;
StreamedImageSize:Integer;
begin
StreamToSend:= TMemoryStream.Create;
ImageStream:= TMemoryStream.Create;
try
CDS1.DisableControls;
CDS1.First;
而不是CDS1.Eof做开始
ImageStream.Clear;
CDS1Graphic.SaveToStream(ImageStream);
ImageStream.Position:= 0;
StreamedImageSize:= ImageStream.Size;
StreamToSend.Write(StreamedImageSize,SizeOf(Integer));
StreamToSend.CopyFrom(ImageStream,StreamedImageSize);
CDS1.Next;
结束
StreamToSend.Position:= 0;
TetheringAppProfile1.Resources.FindByName('BioLife')。值:= StreamToSend;
finally
CDS1.EnableControls;
ImageStream.Free;
结束
结束

客户

  //注意:在客户端,CDS1只有两个字段,一个名为ID,一个
// ftAutoInc字段,Graphic是一个TGraphicField

程序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;
尝试
如果CDS1.Active然后
CDS1.EmptyDataSet //丢弃现有数据
else
CDS1.CreateDataSet;
CDS1.DisableControls;
,而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;
结束
CDS1.First;
finally
ImageStream.Free;
CDS1.EnableControls;
结束
结束

原始答案如下



我已经在您的q Delphi:如何通过使用应用程序绑定从服务器数据库获取所有图像?我认为你对Delphi编程的了解足够能够将数据从Sqlite数据库中获取到TCientDataSet中,但也可能没有。



下面是我的另一个答案的服务器+客户端的代码,适用于使用FireDAC组件而不是TClientDataSets。再次,它使用服务器数据集的 SaveToStream 方法将其数据保存在服务器的流中,客户端上的 LoadFromStream



请注意,客户端应用程序中只有两行代码。



FDApp1代码: / p>

  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;
结束

[...]

程序TApp1Form.btnConnectClick(发件人:TObject);
begin
TetheringManager1.AutoConnect;
结束

程序TApp1Form.btnSendStreamClick(Sender:TObject);
begin
DataSetToStream;
结束

程序TApp1Form.FormCreate(发件人:TObject);
begin
Caption:= Format('App1:%s',[TetheringManager1.Identifier]);
FDQuery1.LoadFromFile('D:\D10\Samples\Data\BioLife.FDS');
结束

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

程序TApp1Form.DataSetToStream;
var
流:TMemoryStream;
begin
Stream:= TMemoryStream.Create;
FDQuery1.SaveToStream(Stream);
Stream.Position:= 0;
TetheringAppProfile1.Resources.FindByName('BioLife')。值:= Stream;
结束

FDApp2代码:

 键入
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;

[...]
程序TApp2Form.TetheringAppProfile1Resources0ResourceReceived(const Sender:
TObject; const AResource:TRemoteResource);
begin
AResource.Value.AsStream.Position:= 0;
FDMemTable1.LoadFromStream(AResource.Value.AsStream);
结束

当然,在客户端,如果由于某种原因想要图像(但不是其他服务器数据)复制到另一个数据集中,您可以通过逐行副本执行此操作,类似于qs中的代码。


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 "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;

解决方案

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.

这篇关于如何使用应用程序捆绑从服务器获取图像的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆