简体   繁体   English

Delphi datasnap将图像从发送到服务器(存储在数据库中)

[英]Delphi datasnap send an from image to server (to be stored in database)

I have searched high and low for a working solution for sending an image (eg tpngimage) to the server using a datasnap method - but I cannot make it to work. 我在上下搜索了一个可行的解决方案,以使用datasnap方法将图像(例如tpngimage)发送到服务器-但我无法使其正常工作。

When I load the image and save it to a memorystream, I'm able to read the image back from the stream - locally in the client, which is not really a surprise. 当我加载图像并将其保存到内存流时,我能够从流中读取图像-在客户端本地,这并不奇怪。 But when the server method gets called, the stream is nil and contains nothing, the other parameters are fine (simple datatype and an object). 但是,当调用服务器方法时,流为nil并且不包含任何内容,其他参数也很好(简单的数据类型和对象)。

Did I miss something obvious here? 我想念这里明显的东西吗? I was under the impression that TStream is a valid datatype for datasnap methods, but maybe I'm wrong? 我的印象是TStream是datasnap方法的有效数据类型,但也许我错了吗?

The from client side it looks like this. 来自客户端的看起来像这样。

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('.\images\075.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;

And the proxy method looks like this 和代理方法看起来像这样

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;

The Server method looks like this - it fails due to the APictureStream is nil. 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;

When you call APicture.LoadFromStream(AStream); 当您调用APicture.LoadFromStream(AStream); the stream's position goes to the end, and therefore when passing it into ClientModule1 it does not have any data left to be read. 流的位置移到最后,因此,当将其传递到ClientModule1它没有任何要读取的数据。 Either get rid of the unnecessary portion where you write the stream to a TPngImage or reset the stream's position back to 0 just after that part. 摆脱不必要的部分,将流写入TPngImage或在该部分之后将流的位置重置为0。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM