我有2个应用程序让我们打电话给服务器和客户端。
我正在使用Delphi-xe8。应用程序 - >多设备应用程序
在双方使用:App tethering [tManager,tAProfile],SQLite数据库。
在Server SQLite数据库中,我有6张图片。我想在客户端查看该图像。
在客户端我已经6 [TImage]。
当我点击按钮'获取图像列表'时,我得到6张具有相同视图的图像。
我希望以不同的方式查看6张图片.-> [从服务器数据库获取]
客户端“获取图片列表”按钮代码:
procedure TForm1.GetImgLstClick(Sender: TObject);
begin
tAProfile.SendString(tManager.RemoteProfiles.First,'GetImages','');
end;
服务器收到的代码:
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;
客户收到的代码:
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;
答案 0 :(得分:2)
更新:我从您最近的评论中收集到您要发送的内容 图像一个接一个。
问题是Delphi数据集的TGraphicField支持多种格式 它可能是可变大小的,所以如果你只是把它们写到服务器的出站 流,客户端没有办法知道,在读取流时,在哪里 一个图像的数据结束,下一个图像的数据开始。一个简单的解决方案就是拥有 服务器在写入图像之前将图像的大小写入流中 数据到流,并获取客户端的代码来读取图像大小 知道后面有多少是图像的数据。
我回到我发布到您使用TClientDataSets的其他q(Delphi: How to Get All Images From Server Database by using App tethering?)的答案, 但要对其进行调整,使其仅在流中发送图像(及其大小)。该 代码仍然非常简单,原则上与使用FireDAC数据集和Sqlite数据表没有区别:
服务器
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;
客户端
// 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;
原始答案如下
我已经向您展示了一种在我对q Delphi: How to Get All Images From Server Database by using App tethering?的回答中使用TClientDataSets在服务器和客户端应用之间移动图像的一种非常简单的方法。我假设你对Delphi编程有足够的了解,能够将你的Sqlite数据库中的数据转换成TCientDataSet,但也许不行。
以下是我的另一个答案的服务器+客户端的代码,适用于使用FireDAC组件而不是TClientDataSets。同样,它使用服务器数据集的SaveToStream
方法将其数据保存到服务器的流和客户端的LoadFromStream
。
请注意,客户端应用程序中只有两行代码。
FDApp1代码:
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代码:
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;
当然,在客户端,如果由于某种原因你想要将图像(但不是其他服务器数据)复制到另一个数据集中,你可以通过逐行复制来实现,类似于你的qs。