【问题标题】:Sending large data from WCF Server to Delphi Client将大数据从 WCF 服务器发送到 Delphi 客户端
【发布时间】:2012-05-30 14:31:04
【问题描述】:

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

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

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

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

我了解到 WCF 能够流式传输数据,您可以在以下位置阅读:How to: Enable Streaming

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

[OperationContract]
Stream GetStream(string data);

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

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

【问题讨论】:

    标签: c# wcf delphi delphi-2010


    【解决方案1】:

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

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

    [OperationContract]
    string DownloadFile(string filePath);
    

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

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

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

    但是最大的优势是任何客户端(移动或一些奇怪的嵌入式设备或任何你可能遇到的)只要它有可用的 http 支持就能够实现这个方案(Delphi 有一些非常好的 http-客户端选项)。

    【讨论】:

    • 您可以实现第二个 WCF REST 服务。这样,Delphi 客户端将从 DownloadFile 方法获取下载 URL,该方法创建一个临时 URL(指向 REST 服务),REST 服务可以检查其有效性并提供下载。例如,您可以创建一个令牌并将其存储在数据库中(带有到期时间和文件信息)。 URL 可以包含令牌(例如:localhost:15000/RestService/)。 REST 服务可以检查数据库的令牌过期情况并提供文件。
    【解决方案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 中,您会通过方法调用获得一个流。然后,您可以将该流的内容复制到 TFileStream 中,就像源是 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 访问它一样。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2013-04-11
      • 2021-12-07
      • 2012-09-02
      • 1970-01-01
      • 1970-01-01
      • 2012-11-09
      • 2011-07-13
      • 2012-08-29
      相关资源
      最近更新 更多