DataSnap REST JavaScript 客户端 – 如何显示从 TServerMethods 方法返回为 TStream 的 pdf 文件数据
Posted
技术标签:
【中文标题】DataSnap REST JavaScript 客户端 – 如何显示从 TServerMethods 方法返回为 TStream 的 pdf 文件数据【英文标题】:DataSnap REST JavaScript client-side – How to show pdf file data returned as TStream from a TServerMethods method 【发布时间】:2014-09-05 11:46:24 【问题描述】:我有一个 DataSnap 服务器方法
function TServerMethods.GetFile(filename): TStream
返回一个文件。 在我的测试用例中,该文件是一个简单的 .PDF。
我确信这个功能可以正常工作,因为我能够在 ObjectiveC 客户端应用程序上打开文件,在该应用程序中我使用了我自己的对 DataSnap 方法的 http 调用(没有 Delphi 代理)。 流从 ASIHttpRequest 对象中读取并保存为本地文件,然后加载并定期显示在标准 pdf 阅读器中。 我不知道 ASIHttpRequest 究竟是如何管理返回的数据的。
但是在我使用标准的 javascript 客户端
stream = ServerMethods().GetFile('test.pdf')
DataSnap 代理本身提供的 JavaScript 函数,我不知道如何向用户显示 .pdf 数据。
使用
window.open().document.write(stream);
一个新的浏览器窗口打开,其中包含文本原始数据 ( %PDF-1.5 %âãÏÓ 1 0 obj
有
window.open("data:application/pdf;base64," +stream);
我得到一个空的新浏览器页面。
与
window.open("data:application/pdf," +stream);
或
document.location = 'data:application/pdf,'+encodeURIComponent(serverMethods().GetFile('test'));
我得到一个带有 pdf empry reader 的新浏览器页面并警告“此 PDF 文档无法正确显示”
没有任何变化:
GetInvocationMetadata().ResponseContentType := 'application/pdf';
进入 DataSnap 函数。
我没有其他想法...
编辑
任务是下载一般文件,而不仅仅是 PDF。 PDF 只是一个测试。 GetFile
必须管理 .pdf、.xlsx、.docx、.png、.eml 等...
【问题讨论】:
有没有办法将资源数据(这里是PDF文档流)与DataSnap中的http://example.com/resources/mypdf
等Web资源地址关联起来?然后window.open('http://example.com/resources/mypdf')
应该可以工作。
谢谢@mjn。创建服务器端文件资源是一种选择,我会尝试的。我也会尝试从 JavaScript 直接 URL 调用 DataSnap REST 方法,绕过代理。
您正在创建什么类型的 REST 服务器?哪个法师? DataSnap REST 服务器应用程序向导中存在一个错误,导致无法覆盖 ResponseContentType。
嗨@AndersE.Andersen,我读到了你的answer,我尝试了完整的JavaScript 设计,但没有成功。我已经使用 Delphi XE3,DataSnap Rest 应用程序向导,独立用于调试目的。但是现在有了直接的 URL 请求localhost/datasnap/rest/TserverMethods/GetFile/test.pdf,pdf 最终会被浏览器正确显示。但如果可能的话,我正在寻找一种纯 JavaScript 设计。
好吧,那听起来不像是错误导致了这个特定问题。您是否尝试过先调用 document.open("application/pdf") 然后调用 document.write(..pdf-data..) 最后调用 document.close()?
【参考方案1】:
设置 ResponseContentType 后,您的服务器端代码将按预期工作。您可以通过直接从浏览器调用该方法来测试它。更改类名以匹配您正在使用的类名:
http://localhost:8080/datasnap/rest/TServerMethods1/GetFile/test.pdf
我确信有一种方法可以在浏览器端正确显示流,但我不确定那是什么。除非您对流进行特殊处理,否则我建议您直接获取文档或使用 Web 操作并避开浏览器。基本上是 mjn 的建议。
我能想到几个解决方案。
1) 一种快速的方法是允许直接访问文档。
在 WebFileDispatcher 中,添加一个 WebFileExtension。选择 .pdf,它将为您填写 MIME 类型。假设您的 pdf 文档位于“docs”文件夹中,则 url 可能如下所示:
http://localhost:8080/docs/test.pdf
2) 我可能会在 web 模块上添加一个操作。它涉及更多一点,但它也给了我更多的控制权。
使用这个网址:
http://localhost:8080/getfile?filename=test.pdf
在 web 操作处理程序中这样的代码(没有检查或错误处理)。 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;
【讨论】:
谢谢@Bruce,我确认这工作正常。这是一个有用的解决方法,但我真正的问题是,是否可以处理从 JSON 响应中的 JSON 调用返回的 PDF 流数据,如 DataSnap 框架提供的那样,只是为了显示它。在应用程序或桌面应用程序中,我们可以保存 PDF 流并将其显示给用户,我们可以在 AJAX 查询中获取数据并等待回调,我们可以在显示之前处理流等等。有没有办法做到这一点在浏览器 JavaScript Web 应用程序中?听起来不像。 @布鲁斯。我设法让您的第二个建议(操作)在我的 Rest 服务器中工作,但请求是空的。有什么想法吗?以上是关于DataSnap REST JavaScript 客户端 – 如何显示从 TServerMethods 方法返回为 TStream 的 pdf 文件数据的主要内容,如果未能解决你的问题,请参考以下文章
idhttp.post方式 调用datasnap rest 远程方法
DATASNAP REST WEBSERVICES中间件如何跨平台使用