Мне нужно опубликовать файл 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. Спасибо за любую помощь.