How to send Stream Parameter to EMSDataSetResource

  

I need to post a pdf file to a firebird database using Rad Server with a TEMSDataSetResource and am trying to send the file as a parameter.

I have created a simple table using Firebird 3.0 on Linux Ubuntu 18.04 with a text field and a Blob Binary Field.

The SQL in the qryPost is:

insert into Table01 (FileName,FileData)
values (:FileName,:FileData)

I created a sample that connects directly to the DataBase and the following code works to post the blobs. I have a full pot of coffee and will try again using EMSDataSetResource and post an update.

procedure THeaderFooterForm.btnGetAllClick(Sender: TObject);
begin
qryGetAll.Open(‘Select * From Table01’);
end;

procedure THeaderFooterForm.btnPostClick(Sender: TObject);

var Stream:TMemoryStream;

begin
qryPost.ParamByName(‘FileName’).AsString := Edit1.Text;
stream := TMemoryStream.Create;
Try
stream.LoadFromFile(edit2.Text);
stream.Seek(0,0);
qryPost.ParamByName(‘FileData’).LoadFromStream(stream,ftBlob);
qrypost.OpenOrExecute;
Finally
stream.Free;
End;
end;

procedure THeaderFooterForm.SpeedButton1Click(Sender: TObject);
begin
if OpenDialog1.Execute then
Edit2.Text := OpenDialog1.FileName
else
Edit2.Text := ”;
end;

I am now adding a new project of a RAD Server Package. Create Package with Resource name of ‘Blob’ and as a Data Module with DataBase Endpoints and no Sample Endpoints. Select Connection to Database and Select Table01 and FINISH.

Same SQL

insert into Table01 (FileName,FileData)
values (:FileName,:FileData)

and set param types both to ptinput and data types to ftstring and ftblob and set default param values. Execute the query at design time and it correctly posts string value to the blob field.

Separate issue and side note. I am using Rad Studio 10.3 and compiling the EMS server comes up with error that required package FireDacFBDriver not found. My work around is to remove FireDacFBDriver.dcp from the requires section of the project. Recompile and it asks to add the FireDacIBDriver which seems to work.

Here is the complete and amazingly short code for the EMS Server Package. All I changed is the ResourceSuffix name to ‘Test’.

unit Server_u;

// EMS Resource Module

interface

uses
System.SysUtils, System.Classes, System.JSON,
EMS.Services, EMS.ResourceAPI, EMS.ResourceTypes, FireDAC.Stan.Intf,
FireDAC.Stan.Option, FireDAC.Stan.Error, FireDAC.UI.Intf, FireDAC.Phys.Intf,
FireDAC.Stan.Def, FireDAC.Stan.Pool, FireDAC.Stan.Async, FireDAC.Phys,
FireDAC.Phys.FB, FireDAC.Phys.FBDef, FireDAC.ConsoleUI.Wait,
FireDAC.Stan.Param, FireDAC.DatS, FireDAC.DApt.Intf, FireDAC.DApt,
EMS.DataSetResource, Data.DB, FireDAC.Comp.DataSet, FireDAC.Comp.Client;

type
[ResourceName(‘Blob’)]
TBlobResource1 = class(TDataModule)
FDConnection1: TFDConnection;
qryTABLE: TFDQuery;
[ResourceSuffix(‘Test’)]
dsrTABLE: TEMSDataSetResource;

published
end;

implementation

{%CLASSGROUP ‘System.Classes.TPersistent’}

{$R *.dfm}

procedure Register;
begin
RegisterResource(TypeInfo(TBlobResource1));
end;

initialization
Register;
end.

Setting up the EMS client basically following this tutorial but using Firemonkey multi device.

http://docwiki.embarcadero.com/RADStudio/Rio/en/Tutorial:_Implementing_a_FireDAC_RAD_Server_Client_Application

The resource on the EMSFireDacClient is set to ‘blob/test/’ and needs the trailing /

Dropped a TGrid and livebinding it to the memtable .

Had to modify SQL slightly since the EMSFireDacClient.getdata has to have data returned.

insert into Table01 (FileName,FileData)
values (:FileName,:FileData)
returning Filename,FileData;

Tested on client with this procedure to make sure that it works and posts with string parameters.

procedure THeaderFooterForm.btnPostClick(Sender: TObject);
var Stream:TMemoryStream;

begin
EMSFireDacClient1.GetEndpoint.Params.Clear;
EMSFireDacClient1.GetEndpoint.AddParameter(‘FileName’,edit1.Text);
stream := TMemoryStream.Create;
Try
stream.LoadFromFile(edit2.Text);
stream.Seek(0,0);
EMSFireDacClient1.GetEndpoint.AddParameter(‘FileData’,Edit2.Text);
EMSFireDacClient1.GetData;
Finally
stream.Free;
mtblob.Refresh //refresh memtable
End;
end;

All works well and this is where I am stuck. I can’t figure out how to use a stream parameter with TEMSFireDacClient.

There is no Loadfromstream for params, only addparameter which takes only string value. Some setstream procedure on parambyname but doesn’t seem to work and posts the text value. Here is what I tried and I am stumped.

procedure THeaderFooterForm.btnPostClick(Sender: TObject);

var Stream:TMemoryStream;

begin
EMSFireDacClient1.GetEndpoint.Params.Clear;
EMSFireDacClient1.GetEndpoint.AddParameter(‘FileName’,edit1.Text);
stream := TMemoryStream.Create;
Try
stream.LoadFromFile(edit2.Text);
stream.Seek(0,0);
EMSFireDacClient1.GetEndpoint.AddParameter(‘FileData’,edit2.Text);
EMSFireDacClient1.GetEndpoint.Params.ParameterByName(‘FileData’).SetStream(stream,ooCopy);
EMSFireDacClient1.GetData;
Finally
stream.Free;
mtblob.Refresh //refresh memtable
End;
end;

This seems the correct way to add and access the second param but still no luck. It runs and posts the text field but nothing to the blob field.

procedure THeaderFooterForm.btnPostClick(Sender: TObject);

var Stream:TMemoryStream;
aParam: TRESTRequestParameter;

begin
EMSFireDacClient1.GetEndpoint.Params.Clear;
EMSFireDacClient1.GetEndpoint.AddParameter(‘FileName’,edit1.Text);
stream := TMemoryStream.Create;
Try
stream.LoadFromFile(edit2.Text);
stream.position := 0;
aParam := EMSFiredacClient1.GetEndpoint.Params.AddItem;
aParam.Name := ‘FileData’;
aParam.SetStream(stream,ooCopy); //also tried ooRest and ooApp
EMSFireDacClient1.GetData;
Finally
//stream.Free;
mtblob.Refresh //refresh memtable
End;
end;

I am stumped. Do I need a different approach sending file in header or body of Rest request, but then what do I do on the server side. I can’t find any examples at all of the EMSDataSetResouce with blob fields. Thanks for any help.

Comments are closed.