Как отправить параметр потока в EMSDataSetResource - PullRequest
0 голосов
/ 20 октября 2019

Мне нужно опубликовать файл pdf в базе данных Firebird, используя Rad Server с TEMSDataSetResource, и я пытаюсь отправить файл в качестве параметра.

Я создал простую таблицу с использованием Firebird 3.0 в Linux Ubuntu 18.04с текстовым полем и двоичным полем BLOB-объекта.

SQL в qryPost:

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

Я создал образец, который подключается непосредственно к базе данных, и следующий код работает для публикациисгустки. У меня есть полный горшок кофе, и я попытаюсь снова использовать EMSDataSetResource и опубликовать обновление.

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;

Я сейчас добавляю новый проект пакета RAD Server. Создайте пакет с именем ресурса «Blob» и в качестве модуля данных с конечными точками базы данных и без выборочных конечных точек. Выберите Соединение с базой данных и выберите Table01 и FINISH.

Тот же SQL

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

и задайте для типов параметров как ptinput, так и для типов данных ftstring и ftblob и установите значения параметров по умолчанию. Выполните запрос во время разработки, и он правильно отправит строковое значение в поле большого двоичного объекта.

Отдельный выпуск и примечание. Я использую Rad Studio 10.3 и при компиляции сервера EMS возникает ошибка, из-за которой требуемый пакет FireDacFBDriver не найден. Моя работа заключается в том, чтобы удалить FireDacFBDriver.dcp из необходимого раздела проекта. Перекомпилируйте, и он просит добавить FireDacIBDriver, который, кажется, работает.

Вот полный и удивительно короткий код для пакета сервера EMS. Все, что я изменил, это имя ResourceSuffix на «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.

Настройка клиента EMS в основном в соответствии с этим учебником, но с использованием нескольких устройств Firemonkey.

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

Ресурсу в EMSFireDacClient присвоено значение 'blob / test /', для которого требуется завершающий /

Удалил TGrid и привязал его к мемблите в реальном времени.

Пришлось немного изменить SQL, так как EMSFireDacClient.getdata должен возвращать данные.

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

Протестировано на клиенте с помощью этой процедуры, чтобы убедиться, что оно работает и отправляет сообщения со строковыми параметрами.

    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;

Все работает хорошо, и этогде я застрял. Я не могу понять, как использовать параметр потока с TEMSFireDacClient.

Нет никакого Loadfromstream для параметров, только addparameter, который принимает только строковое значение. Некоторая процедура settream для parambyname, но, кажется, не работает и отправляет текстовое значение. Вот то, что я пытался, и я в тупике.

    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;

Кажется, это правильный способ добавить и получить доступ ко второму параметру, но все равно не повезло. Он запускает и отправляет текстовое поле, но ничего в поле BLOB-объекта.

    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;

Я в тупике. Нужен ли другой способ отправки файла в заголовке или теле запроса Rest, но что мне делать на стороне сервера? Я не могу найти никаких примеров на EMSDataSetResouce с полями BLOB. Спасибо за любую помощь.

1 Ответ

0 голосов
/ 28 октября 2019

Итак, я завершил загрузку pdf в виде большого двоичного объекта, используя полностью EMSDataSetResource с конечной точкой базы данных. Моя трудность заключалась в том, чтобы правильно разместить блоб в мембите на стороне клиента. Итак, вот что сработало.

Создайте пакет на стороне сервера, но оставьте SQL как созданный.

select * from TABLE01

Настройте клиент с помощью приведенного выше учебника Embacadero.

Получитьданные с простыми

EMSFireDacclient1.GetData;

Добавить новую запись в FDMemTable

procedure THeaderFooterForm.AppendButtonClick(Sender: TObject);

var
  aStream:TMemoryStream;
begin
  mtblob.Append;
  mtblob.FieldByName('filename').AsString := edit1.Text;
  aStream := TMemoryStream.Create;
  try
    aStream.LoadFromFile(edit2.Text);
    aStream.Position := 0;
    (mtblob.FieldByName('filedata') as TBlobField).LoadFromStream(aStream);
  finally
    mtblob.Post;
    aStream.Free;
  end;
end;

и отправить обновления на сервер

procedure THeaderFooterForm.UpdateButtonClick(Sender: TObject);
begin
  emsfiredacclient1.PostUpdates;
end;
...