0

我需要创建一个具有下载文件功能的 WCF 服务。此 WCF 将由 Delphi 应用程序使用。

问题:将要下载的文件非常大,可能会导致Delphi端出现内存问题。到目前为止,我有这个代码:

[OperationContract]
byte[] DownloadFile(string filePath);

但是此代码将导致客户端应用程序将所有数据保存在内存中,这可能是一个问题。

我已经读到 WCF 能够流式传输数据,您可以在以下位置阅读:如何:启用流式传输

但我对从 MSDN 截取的这段代码有疑问:

[OperationContract]
Stream GetStream(string data);

在客户端,我想将 a 传递TFileStream给函数。通过使用TFileStream每个字节读取将直接进入磁盘。但是函数返回一个流,而我想要的将是不可能的,因为流不是函数的参数。

如何将文件从 WCF 服务直接下载到磁盘?

4

2 回答 2

5

我发现在使用其他(非.NET)客户端时依赖 WCF 中的“内置”流功能是奇怪问题的一大来源......

基本上我们通过定义来解决这种情况:

[OperationContract]
string DownloadFile(string filePath);

该方法生成一个 HTTP(S) url 并返回它......

这样,任何支持 http 的客户端都可以以稳健的方式处理数据......

请注意,这会使服务器变得更加复杂,因为您现在需要一些机制来生成(并在其上提供 HTTP GET)URL(安全性、“全局”唯一性、只能在有限的时间内使用等)。

BUT the big advantage is that any client out there (mobile or some strange embedded device or whatever you might encounter) will be able to implement this scheme as long as it has http-support available (Delphi has some very good http-client options).

于 2012-05-30T14:57:37.603 回答
2

首先,我不确定您是否可以在 Delphi 2010 中使用流式 WCF 服务。如果可以,那么它的工作原理如下:

WCF 服务必须是流式服务,这意味着您需要将transferMode绑定的 设置为StreamedStreamedResponse。如果你想传入一个字符串作为参数,它必须是StreamedResponse,否则,参数也必须是一个流。

拥有流式服务还意味着没有方法不返回流或void. 例如,当它是流式服务时,不可能在同一服务中具有以下两种方法。

Stream GetStream(string s);
int GetInteger(string s);

也不可能拥有:

Stream GetStream(string s);

在配置为 的服务中Streamed,因为参数也必须是流。

不可能使用将被“填充”的流调用该方法,即使您使该方法带有一个参数 - 不是在该点来回传递Stream的真实实例,而是内容实际上被复制回来和Stream向前。

在 Delphi 中,您将通过方法调用获得一个流。然后,您可以将该流的内容复制到 aTFileStream中,就像源是 Delphi 中的另一个流一样。可以用谷歌搜索代码。基本上阿德里亚诺已经发布了一些应该工作的东西。基本上:从源流读取,写入目标流,直到所有内容都被读取和写入,或者您可以尝试类似的操作:

stream1 := wcfServiceClient.GetTheStream();
try
    stream2:= TFileStream.Create('to.txt', fmCreate);
    try
        stream2.CopyFrom(stream1, stream1.Size);
    finally
        stream2.Free;
    end;
finally
    stream1.Free;
end;

同样:这仅在您可以从 Delphi 访问 WCF 流服务的假设下有效,就像您从 C# 或 VB.NET 访问它一样。

于 2012-05-30T14:43:48.517 回答