更新:我从你最近的评论中收集到你想发送你的
一张一张的图片。
一个问题是 Delphi 数据集的 TGraphicField 支持多种格式
这可能是可变大小的,所以如果你只是将它们写入服务器的出站
流,客户端无法知道,当读取流时,
一张图像的数据结束,下一张开始。一个简单的解决方案是
服务器在写入图像的大小之前将图像的大小写入流
数据到流中,并获取客户端的代码以读取图像大小,以便它
知道后面有多少是图像的数据。
我要回到我发布给你的另一个 q (Delphi: How to Get All Images From Server Database by using App tethering?) 的答案,它使用 TClientDataSets,
但对其进行调整,使其仅发送流中的图像(及其大小)。这
代码仍然很简单,原则上应该与使用 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;
当然,在客户端,如果出于某种原因您希望将图像(而不是其他服务器数据)复制到另一个数据集中,您可以通过逐行复制来完成,类似于中的代码你的问题。