我有一个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<< / Type / Catalog / Pages 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 empry阅读器的新浏览器页面并提醒“此PDF文档无法正确显示”
没有任何改变添加:
GetInvocationMetadata().ResponseContentType := 'application/pdf';
进入DataSnap函数。
我没有其他想法......
修改
该任务用于一般文件下载,而不仅仅是PDF。 PDF仅供测试。 GetFile
必须管理.pdf,.xlsx,.docx,.png,.eml等......
答案 0 :(得分:1)
设置ResponseContentType后,服务器端代码将按预期工作。您可以直接从浏览器调用该方法来测试它。更改班级名称以匹配您正在使用的班级名称:
http://localhost:8080/datasnap/rest/TServerMethods1/GetFile/test.pdf
我确定可以在浏览器端正确显示流,但我不确定那是什么。除非您对流做了一些特别的事情,否则我建议您直接获取文档或使用网络操作并退出浏览器。基本上是mjn建议的。
我可以想到几个解决方案。
1)快速的方法是允许直接访问文档。
在WebFileDispatcher中,添加WebFileExtension。选择.pdf,它会为你填写mime类型。假设您的pdf文档位于" docs"文件夹,网址可能如下所示:
http://localhost:8080/docs/test.pdf
2)我可能会在网络模块上添加一个动作。它涉及的更多,但它也让我有更多的控制权。
使用此网址:
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;