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;