Rad Server: Get bmp/jpeg from EMS Server to Mobile Client using a pathname

262 Views Asked by At

I have a mobile delivery application using Rad Server that allows the user to scan a barcode and take pictures of the delivery from their phone and then send them to the server which stores the picture in a specific directory. It then stamps the file name to the order for future reference.

Now I would like the user to access the picture using a pathname parameter and display it on the mobile app when required. I have tried to google an acceptable solution but have not found anything that works.

I did find this post which seems to be what I want but I can't get it to work:

RAD Server 10.4.2 Duplicate Endpoints

and I checked out David Intersimone's youtube video. Using his example on the server side gives me the following error when I include the code:

[ResourceSuffix('*')]
[EndpointProduce ('image/jpeg')]
procedure GetImage(const AContext: TEndpointContext; const ARequest: TEndpointRequest; const AResponse: TEndpointResponse);

enter image description here

If I remove the 'EndpointProduce' line I get the following error message:

enter image description here

The code I am executing is:

procedure TdmCapture.GetImage(const AContext: TEndpointContext; const ARequest: TEndpointRequest; const AResponse: TEndpointResponse);
var fs: TFileStream;
begin
//  FileName := ARequest.Params.Values['FileName'];
//  fs := TFileStream.Create(FileName, fmOpenRead);
  fs := TFileStream.Create('c:\temp\Montreal.jpg', fmOpenRead);
  AResponse.Body.SetStream(fs, 'image/jpeg', True);
end;

The objective is to send a request to the server from the mobile device with the full pathname of the image. The server then accesses the image and sends it back to the mobile app to be displayed.

I am running Delphi 11 on Windows 10 Pro.

I am testing using jpg files but but what I really want to do is implement the solution for bmp files.

I have also tried to remove the 'EndpointProduce' Line and go with the following code:

  FileName := ARequest.Params.Values['FileName'];
  FileName := 'c:\temp\Montreal.jpg';

  fs := TFileStream.Create(FileName, fmOpenRead);
  AResponse.Headers.SetValue('Content-Type', 'application/json; charset=utf-8');
  AResponse.Body.SetStream(fs, 'image/jpeg', True);

This produces the following error message which I have also not found a solution for:

enter image description here

I modified my Server side code to use a JSON Array as follows:

procedure TdmCapture.GetImage(const AContext: TEndpointContext; const ARequest: TEndpointRequest; const AResponse: TEndpointResponse);
var ms: TMemoryStream;
    FileName: string;
    jsonArray: TJSONArray;
begin
  FileName := ARequest.Params.Values['FileName'];
  ms := TMemoryStream.Create;

  try
    ms.LoadFromFile(FileName);

    jsonArray := TJSONArray.Create;
    jsonArray := TDBXJSONTools.StreamToJSON(ms, 0, ms.Size);
    AResponse.Body.SetValue(jsonArray, true);
  finally
    ms.Free;
  end;
end;

This appears to work as when I run it from a browser I get a large array of values.

Obviously, I have to modify my Client side call to process the JSON Array. However, I am unsure how to do that. When I execute the 'GetData' call I receive the error:

enter image description here

My client code is as follows:

  dmCaptureClient.EMSFDClientImages.Resource := 'Capture/GetImage';
  dmCaptureClient.EMSFDClientImages.GetEndpoint.AddParameter('FileName', dmCaptureClient.FDMTFAAttach.FindField('COMMAND').AsString);
  dmCaptureClient.EMSFDClientImages.GetData;


  if not dmCaptureClient.FDMTImages.EOF then
  begin
// Load the image into a TImage component
  end

The components I use are TFDMemTable, TEMSFireDACClient, TFDSchemaAdapter and TFSTableAdpater.

enter image description here

I tried a different approach of using a TBackendEndPoint Component to convert the JSON passed from the server to an image using the following code:

procedure TdmCaptureClient.BackendEndpointGetImageAfterExecute(Sender: TCustomRESTRequest);
var s: TStream;
    JSONArray: TJSONArray;
    myImage: TImage;
begin
  JSONArray := TJSONObject.ParseJSONValue(BackendEndpointGetImage.Response.JSONText) as TJSONArray;

   try
     s := TDBXJSONTools.JSONToStream(jsonArray);
     try
       s.Position := 0;
       myImage.Bitmap.LoadFromStream(s);
     finally
       s.Free;
     end;
   finally
     jsonArray.Free;
   end;
end;

The JSONArray is populated with data but it appears that the TDBXJSONTools.JSONToStream function returns an empty stream and then I get an AV when I try to load the stream into my image.

I seem to recall another post that said there was a problem with TDBXJSONTools.JSONToStream.

1

There are 1 best solutions below

0
Leonard M. On

Well, it appears that I was on the right track with using the BackendEndPoint component to process the JSON that was sent from the server.

With the help of Embarcadero support I was able to accomplish the task with the following code on the Client side:

procedure TLumberNowFrame.wwDataGrid1DblClick(Sender: TObject);
var
  ImageValue : TJSONValue;
  ImageStream : TStream;
  Image : TBitmap;
begin
  dmCaptureClient.BackendEndpointGetImage.Params.Items[0].Value := dmCaptureClient.FDMTFAAttach.FindField('COMMAND').AsString;
  dmCaptureClient.BackendEndpointGetImage.Execute;

  ImageValue := dmCaptureClient.BackendEndpointGetImage.Response.JSONValue;
  ImageStream := TDBXJSONTools.JSONToStream(ImageValue as TJSONArray);
  ImageStream.Position := 0;
  try
    Image := TBitmap.Create;
    Image.LoadFromStream(ImageStream);
    Image1.Bitmap := Image;
  finally
    Image.Free;
  end;
end;

The server side code was correct