1

我有一个 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 reader 的新浏览器页面并警告“此 PDF 文档无法正确显示”</p>

没有任何改变添加:

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

进入 DataSnap 函数。

我没有其他想法...

编辑

任务是下载一般文件,而不仅仅是 PDF。PDF 只是一个测试。GetFile必须管理 .pdf、.xlsx、.docx、.png、.eml 等...

4

1 回答 1

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)我可能会在网络模块上添加一个动作。它涉及更多一点,但它也给了我更多的控制权。

使用这个网址:

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;
于 2014-09-06T22:29:07.413 回答