我需要创建一个具有下载文件功能的WCF服务。这个WCF将由Delphi应用程序使用。
问题:将要下载的文件非常大,可能会导致Delphi端出现内存问题。到目前为止,我有这段代码:
[OperationContract]
byte[] DownloadFile(string filePath);
但是这段代码会导致客户端应用程序将所有数据保存在内存中,这可能是一个问题。
我已经读过WCF能够传输数据,您可以阅读:How to: Enable Streaming
但我对从MSDN中删除的这段代码有疑问:
[OperationContract]
Stream GetStream(string data);
在客户端,我想将TFileStream
传递给该函数。通过使用TFileStream
每个字节读取将直接进入磁盘。但函数RETURNS一个流和我想要的东西是不可能的,因为流不会是函数的参数。
如何将文件从WCF服务直接下载到磁盘?
答案 0 :(得分:5)
我发现在与其他(非.NET)客户端合作时依赖WCF中的“内置”流功能是导致奇怪问题的重要原因......
基本上我们通过定义来解决这种情况:
[OperationContract]
string DownloadFile(string filePath);
该方法生成一个HTTP(S)url并返回它......
这样任何支持http的客户端都能以健壮的方式处理数据......
请注意,这会使服务器变得更复杂,因为您现在需要一些机制来生成(并提供HTTP GET)URL(安全性,“全局”唯一,仅在有限时间内可用等)。 / p>
但最大的好处是任何客户端(移动设备或某些奇怪的嵌入式设备或您可能遇到的任何设备)都能够实现此方案,只要它具有可用的http支持(Delphi有一些非常好的http-客户选择)。
答案 1 :(得分:2)
首先,我不确定您是否可以在Delphi 2010中使用流式WCF服务。如果可以,那么它的工作方式如下:
WCF服务必须是流服务,这意味着您需要将绑定的transferMode
设置为Streamed
或StreamedResponse
。如果要将字符串作为参数传入,则必须为StreamedResponse
,否则,参数也必须是流。
拥有流服务还意味着没有方法不会返回流或void
。例如,当它是流服务时,不可能在同一服务中使用以下两种方法。
Stream GetStream(string s);
int GetInteger(string s);
也不可能:
Stream GetStream(string s);
在配置为Streamed
的服务中,因为参数也必须是流。
无法使用将被“填充”的流调用该方法,即使您使该方法采用Stream
参数 - 也不会传递Stream
的实际实例,此时,内容实际上是来回复制的。
在Delphi中,由于方法调用,你会得到一个流。然后,如果源是Delphi中的另一个流,则可以将该流的内容复制到TFileStream
中。代码可以用Google搜索。基本上阿德里亚诺发布了一些应该有用的东西。基本上:从源流中读取,写入目标流直到读取和写入所有内容,或者您可以尝试类似的内容:
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访问它。