Search code examples
imagedelphidelphi-10.1-berlindatasnap

How to send and receive a TMemoryStream (in a TObject) using DataSnap in Delphi 10.1


I have an application written in Delphi 10.1 using REST Datasnap.

This application includes a Client and Server.

The Client is a mobile application (Android) and the Server is a Windows Service that's is connected to a firebird database.

I have an Object:-

TJob = class(TObject)
  private
    FID: Integer;
    FThe_Name: String;
    FImage: TMemoryStream;
  public
    constructor Create;
    destructor Destroy;
  end;

constructor TJob.Create;
begin
  inherited;
  FImage := TMemoryStream.Create;
end;

destructor TJob.Destroy;
begin
  FreeAndNil(FImage);
  inherited;
end;

I get an access violation when I try to save the image on the server to the DB and when I try and open and display the image on the client.

I have a standalone multidevice application that use the same functionality(Getting, Saving and displaying of an Image) as the Client/Server and works.

Client displaying the image on the form:-

if (Job.Image.Size > 0) then
  begin
    rectangle.Fill.Kind := TBrushKind.Bitmap;
    rectangle.Fill.Bitmap.Bitmap.LoadFromStream(Job.Image);
    rectangle.Repaint;
    Layout.Repaint;
  end;

Client getting the Image from the form:-

if not(rectangle.Fill.Bitmap.Bitmap.IsEmpty) then
  begin
    Job.Image.Seek(0, soFromBeginning);
    rectangle.Fill.Bitmap.Bitmap.SaveToStream(Job.Image);
    Job.Image.Position := 0;
  end;

Server Saving the Image to DB:-

  Job.Image.Position := 0;
  (TBlobField(FieldByName('MyImage'))).SaveToStream(Job.Image);

Server getting the Image from DB:-

(TBlobField(FieldByName('MyImage'))).SaveToStream(Job.Image);

The Standalone application works using the same however I get errors when trying to either save or display an image.

I have populated the DB with various formats of images, which I can view in the DB, but not from the Client(AV).

Any ideas on what I've done wrong and examples on how to solve fix?

Thanks


Solution

  • Server getting the Image from DB:-

      PngImage := TPngImage.Create;
      MemoryStream := TMemoryStream.Create;
      try
        (TBlobField(FieldByName('Image'))).SaveToStream(MemoryStream);
        MemoryStream.Position := 0;
        PngImage.LoadFromStream(MemoryStream);
        Job.Image_AsStr := Base64FromPngImage(PngImage);
      finally
        MemoryStream.Free;
      end;
    

    Client displaying the image on the form:-

      if (Job.Image_AsStr <> '') then
      begin
        rImage.Fill.Kind := TBrushKind.Bitmap;  
        rImage.Fill.Bitmap.Bitmap := BitmapFromBase64(Job.Image_AsStr);
        rCustomer_Signature.Repaint;
        lCustomer_Signature.Repaint;
      end;
    

    Client getting the Image from the form:-

      if not(rImage.Fill.Bitmap.Bitmap.IsEmpty) then
      begin
        rImage.Fill.Kind := TBrushKind.Bitmap;
        Job.Image_AsStr := Base64FromBitmap(rImage.Fill.Bitmap.Bitmap);
      end
      else
        Job.Image_AsStr := '';
    

    Server Saving the Image to DB:-

    if Job.Image_AsStr <> '' then
    begin
      MemoryStream := TMemoryStream.Create;
      try
        PngImage := PngImageFromBase64(Job.Image_AsStr);
        PngImage.SaveToStream(MemoryStream);
        MemoryStream.Position := 0;
        Params[1].LoadFromStream(MemoryStream, ftBlob);
      finally
        MemoryStream.Free;
      end;
    end
    else
      Params[1].Clear;
    

    On my experience the image arrives back at the Server as a PngImage even though its been packaged as a BMP.

    I can now confirm that I've installed and tested on a Android phone. *Note. The original question posted was about using a TMemoryStream, these examples uses a String.