DataSnap REST JavaScript на стороне клиента - как показать данные файла pdf, возвращенные как TStream из метода TServerMethods

У меня есть метод сервера DataSnap

function TServerMethods.GetFile(filename): TStream

возвращая файл. В моем тестовом случае файл является простым.PDF.

Я уверен, что эта функция работает нормально, поскольку я могу открывать файлы в клиентском приложении ObjectiveC, где я использовал свой собственный http-вызов метода DataSnap (без прокси-сервера Delphi). Поток читается из объекта ASIHttpRequest и сохраняется как локальный файл, затем загружается и регулярно показывается в стандартном PDF-ридере. Я не знаю, как именно ASIHttpRequest управляет возвращенными данными.

Но на стороне клиента JavaScript, где я использую стандарт

stream = ServerMethods().GetFile('test.pdf')

Функция JavaScript, предоставленная самим прокси-сервером DataSnap, не позволяет понять, как показать данные в формате PDF пользователю.

С помощью

window.open().document.write(stream);

Откроется новое окно браузера с необработанными текстовыми данными ( %PDF-1.5 %âãÏÓ 1 0 obj << / Тип / Каталог / Страницы 2 0 R …..)

С

window.open("data:application/pdf;base64," +stream);

Я получаю пустую новую страницу браузера.

С

window.open("data:application/pdf," +stream);

или же

document.location = 'data:application/pdf,'+encodeURIComponent(serverMethods().GetFile('test'));

Я получил новую страницу браузера с устройством чтения PDF-файлов и предупреждением "Этот документ PDF не может быть отображен правильно"

Ничего не меняется, добавляя:

GetInvocationMetadata().ResponseContentType := 'application/pdf';

в функцию DataSnap.

У меня нет других идей...

РЕДАКТИРОВАТЬ

Задача для общего скачивания файлов, а не только PDF. PDF только тест. GetFile должны управлять.pdf, .xlsx, .docx, .png, .eml и т. д.

1 ответ

Код на стороне сервера работает, как и ожидалось, после установки ResponseContentType. Вы можете проверить это, вызвав метод непосредственно из браузера. Измените имя класса в соответствии с тем, которое вы используете:

http://localhost:8080/datasnap/rest/TServerMethods1/GetFile/test.pdf

Я уверен, что есть способ правильно отобразить поток на стороне браузера, но я не уверен, что это такое. Если вы не делаете что-то особенное с потоком, я бы порекомендовал получить документ напрямую или использовать веб-действие и выйти из браузера. В основном то, что предложил mjn.

Я могу придумать пару решений.

1) Быстрым способом было бы разрешить доступ к документам напрямую.

В WebFileDispatcher добавьте WebFileExtension. Выберите.pdf, и он заполнит тип MIME для вас. Предполагая, что ваши pdf документы находятся в папке "docs", URL может выглядеть так:

http://localhost:8080/docs/test.pdf

2) Я бы, вероятно, добавил действие на веб-модуль. Это немного сложнее, но это также дает мне больше контроля.

Используя этот URL:

http://localhost:8080/getfile?filename=test.pdf

И такой код в обработчике веб-действий (без проверки или обработки ошибок). Заголовок Content-Disposition предлагает имя файла для загруженного файла:

procedure TWebModule1.WebModule1GetFileActionAction(Sender: TObject;
  Request: TWebRequest; Response: TWebResponse; var Handled: Boolean);
var
  lStream: TMemoryStream;
  lFilename: string;
begin
  lFilename := Request.QueryFields.Values['filename'];
  lStream := TMemoryStream.Create;
  lStream.LoadFromFile('.\Docs\' + lFilename);
  lStream.Position := 0;
  Response.ContentStream := lStream;
  Response.ContentType := 'application/pdf';
  Response.SetCustomHeader('Content-Disposition',
    Format('attachment; filename="%s"', [lFilename]));
end;
Другие вопросы по тегам