Delphi datasnap 从图像发送到服务器(存储在数据库中)
Delphi datasnap send an from image to server (to be stored in database)
我四处寻找使用 datasnap 方法将图像(例如 tpngimage)发送到服务器的可行解决方案 - 但我无法让它工作。
当我加载图像并将其保存到内存流时,我能够从流中读回图像 - 在客户端本地,这并不奇怪。但是当调用服务器方法时,流为 nil 且不包含任何内容,其他参数都很好(简单数据类型和一个对象)。
我是不是漏掉了什么明显的东西?我的印象是 TStream 是数据快照方法的有效数据类型,但也许我错了?
客户端看起来像这样。
function TPerson.Update: Boolean;
var
AStream : TMemoryStream;
APicture : TPngImage;
ASize : Integer;
begin
if (FId > 0) then // if Id below zero we have a problem
begin
ClientModule1.ServerMethods1Client.UpdatePerson(Self);
APicture := TPngImage.Create;
AStream := TMemoryStream.Create;
try
// Temp just use a file
AStream.LoadFromFile('.\images5.png');
ASize := AStream.Size;
AStream.Position := 0; // wind back if needed
// just for testing, we can read back the image from the stream
APicture.LoadFromStream(AStream);
ClientModule1.ServerMethods1Client.UpdatePersonPicture(self, ASize, AStream);
finally
FreeAndNil(AStream);
FreeAndNil(APicture);
end;
end;
FModified := False;
end;
代理方法如下所示
procedure TServerMethods1Client.UpdatePersonPicture(APerson: TPerson; ASize: Integer; APictureStream: TMemoryStream);
begin
if FUpdatePersonPictureCommand = nil then
begin
FUpdatePersonPictureCommand := FDBXConnection.CreateCommand;
FUpdatePersonPictureCommand.CommandType := TDBXCommandTypes.DSServerMethod;
FUpdatePersonPictureCommand.Text := 'TServerMethods1.UpdatePersonPicture';
FUpdatePersonPictureCommand.Prepare;
end;
if not Assigned(APerson) then
FUpdatePersonPictureCommand.Parameters[0].Value.SetNull
else
begin
FMarshal := TDBXClientCommand(FUpdatePersonPictureCommand.Parameters[0].ConnectionHandler).GetJSONMarshaler;
try
FUpdatePersonPictureCommand.Parameters[0].Value.SetJSONValue(FMarshal.Marshal(APerson), True);
if FInstanceOwner then
APerson.Free
finally
FreeAndNil(FMarshal)
end
end;
FUpdatePersonPictureCommand.Parameters[1].Value.SetInt32(ASize);
FUpdatePersonPictureCommand.Parameters[2].Value.SetStream(APictureStream, FInstanceOwner);
FUpdatePersonPictureCommand.ExecuteUpdate;
end;
Server 方法如下所示 - 由于 APictureStream 为 nil 而失败。
procedure TServerMethods1.UpdatePersonPicture(APerson: TPerson; ASize: integer;
APictureStream: TMemoryStream);
var
APicture : TPngImage;
begin
fdqPersons.Close;
fdqPersons.SQL.Clear;
fdqPersons.Connection.StartTransaction;
try
fdqPersons.SQL.Add('update Persons set Picture=:Picture ');
fdqPersons.SQL.Add('where Id=:Id');
fdqPersons.ParamByName('Id').Value := APerson.Id;
APicture := TPngImage.Create;
try
// APicture for testing - but APictureStream is nil!
APicture.LoadFromStream(APictureStream);
fdqPersons.ParamByName('Picture').Assign(APicture);
fdqPersons.ExecSQL;
finally
FreeAndNil(APicture);
end;
fdqPersons.Close;
fdqPersons.Connection.Commit;
LogEvent(format('Person picture updated ID: %d',[APerson.id]));
except
on e:exception do
begin
fdqPersons.Connection.Rollback;
LogEvent(format('Error updating person picture %s',[e.Message]));
raise;
end;
end;
end;
当您调用 APicture.LoadFromStream(AStream);
时,流的位置到达末尾,因此当将它传递到 ClientModule1
时,它没有任何数据可供读取。要么摆脱将流写入 TPngImage
的不必要部分,要么在该部分之后将流的位置重置回 0。
我四处寻找使用 datasnap 方法将图像(例如 tpngimage)发送到服务器的可行解决方案 - 但我无法让它工作。
当我加载图像并将其保存到内存流时,我能够从流中读回图像 - 在客户端本地,这并不奇怪。但是当调用服务器方法时,流为 nil 且不包含任何内容,其他参数都很好(简单数据类型和一个对象)。
我是不是漏掉了什么明显的东西?我的印象是 TStream 是数据快照方法的有效数据类型,但也许我错了?
客户端看起来像这样。
function TPerson.Update: Boolean;
var
AStream : TMemoryStream;
APicture : TPngImage;
ASize : Integer;
begin
if (FId > 0) then // if Id below zero we have a problem
begin
ClientModule1.ServerMethods1Client.UpdatePerson(Self);
APicture := TPngImage.Create;
AStream := TMemoryStream.Create;
try
// Temp just use a file
AStream.LoadFromFile('.\images5.png');
ASize := AStream.Size;
AStream.Position := 0; // wind back if needed
// just for testing, we can read back the image from the stream
APicture.LoadFromStream(AStream);
ClientModule1.ServerMethods1Client.UpdatePersonPicture(self, ASize, AStream);
finally
FreeAndNil(AStream);
FreeAndNil(APicture);
end;
end;
FModified := False;
end;
代理方法如下所示
procedure TServerMethods1Client.UpdatePersonPicture(APerson: TPerson; ASize: Integer; APictureStream: TMemoryStream);
begin
if FUpdatePersonPictureCommand = nil then
begin
FUpdatePersonPictureCommand := FDBXConnection.CreateCommand;
FUpdatePersonPictureCommand.CommandType := TDBXCommandTypes.DSServerMethod;
FUpdatePersonPictureCommand.Text := 'TServerMethods1.UpdatePersonPicture';
FUpdatePersonPictureCommand.Prepare;
end;
if not Assigned(APerson) then
FUpdatePersonPictureCommand.Parameters[0].Value.SetNull
else
begin
FMarshal := TDBXClientCommand(FUpdatePersonPictureCommand.Parameters[0].ConnectionHandler).GetJSONMarshaler;
try
FUpdatePersonPictureCommand.Parameters[0].Value.SetJSONValue(FMarshal.Marshal(APerson), True);
if FInstanceOwner then
APerson.Free
finally
FreeAndNil(FMarshal)
end
end;
FUpdatePersonPictureCommand.Parameters[1].Value.SetInt32(ASize);
FUpdatePersonPictureCommand.Parameters[2].Value.SetStream(APictureStream, FInstanceOwner);
FUpdatePersonPictureCommand.ExecuteUpdate;
end;
Server 方法如下所示 - 由于 APictureStream 为 nil 而失败。
procedure TServerMethods1.UpdatePersonPicture(APerson: TPerson; ASize: integer;
APictureStream: TMemoryStream);
var
APicture : TPngImage;
begin
fdqPersons.Close;
fdqPersons.SQL.Clear;
fdqPersons.Connection.StartTransaction;
try
fdqPersons.SQL.Add('update Persons set Picture=:Picture ');
fdqPersons.SQL.Add('where Id=:Id');
fdqPersons.ParamByName('Id').Value := APerson.Id;
APicture := TPngImage.Create;
try
// APicture for testing - but APictureStream is nil!
APicture.LoadFromStream(APictureStream);
fdqPersons.ParamByName('Picture').Assign(APicture);
fdqPersons.ExecSQL;
finally
FreeAndNil(APicture);
end;
fdqPersons.Close;
fdqPersons.Connection.Commit;
LogEvent(format('Person picture updated ID: %d',[APerson.id]));
except
on e:exception do
begin
fdqPersons.Connection.Rollback;
LogEvent(format('Error updating person picture %s',[e.Message]));
raise;
end;
end;
end;
当您调用 APicture.LoadFromStream(AStream);
时,流的位置到达末尾,因此当将它传递到 ClientModule1
时,它没有任何数据可供读取。要么摆脱将流写入 TPngImage
的不必要部分,要么在该部分之后将流的位置重置回 0。