C#流式传输WCF上传文件

3
我在WCF方面的经验非常有限,我想通过使用流传输方式从客户端机器上传文件到服务器上的WCF服务。我阅读了一些主题,并自己编写了一个简单的示例,但不幸的是它没有起作用。
以下是一个接口代码:
[ServiceContract]
public interface IService1
{      
    [OperationContract]
    string UpStream(FileStream inStream);        
}

这是实现:
public string UpStream(FileStream inStream)
    {
        using(StreamReader sr = new StreamReader(inStream))
        {
            var recievedText = sr.ReadToEnd();

            if (recievedText != "")
            {
                return recievedText;
            }
            else
            {
                return "nothing";
            }
        }           
    } 

这是客户端代码:
 private void button3_Click(object sender, EventArgs e)
    {
        service2.Service1Client sc = new service2.Service1Client();

        OpenFileDialog opf = new OpenFileDialog();
        opf.ShowDialog();
        if (opf.FileName != "")
        {
            using (FileStream inStream = File.Open(opf.FileName, FileMode.Open, FileAccess.Read, FileShare.Read))           
            {                                                       
                  MessageBox.Show(sc.UpStream(inStream));
            }
        }


    }

我认为问题一定在配置文件或数据流中。当我启动客户端程序并调用UpStream方法时,WCF服务接收到一个空的数据流。
    <?xml version="1.0" encoding="utf-8"?>
<configuration>
  <system.web>
    <compilation debug="true" targetFramework="4.0" />
  </system.web>
  <system.serviceModel>
    <services />
    <bindings>
      <basicHttpBinding>
        <binding name="NewBinding0" maxBufferPoolSize="52428800" maxBufferSize="65536000"
          maxReceivedMessageSize="6553600000" transferMode="Streamed"
          useDefaultWebProxy="true" />
      </basicHttpBinding>
    </bindings>
    <behaviors>
      <serviceBehaviors>
        <behavior>       
          <serviceMetadata httpGetEnabled="true"/>     
          <serviceDebug includeExceptionDetailInFaults="false"/>
        </behavior>
      </serviceBehaviors>
    </behaviors>
    <serviceHostingEnvironment multipleSiteBindingsEnabled="true" />
  </system.serviceModel>
 <system.webServer>
    <modules runAllManagedModulesForAllRequests="true"/>  
    <directoryBrowse enabled="true"/>
  </system.webServer>
</configuration>

如果有人能帮我解决我的问题,我会非常感激。

我尝试复制,但当我这么做时,FileStream为空。当我将类型更改为普通流时,它就正常工作了。 - Ykok
1个回答

2

流处理非常有用,但有一些难以理解的地方。

这篇MSDN文章提供了很多细节信息:https://msdn.microsoft.com/en-us/library/ms733742%28v=vs.110%29.aspx

但有些细节并不是非常清晰。

首先,您需要传递消息而不是参数。

看起来会像这样:

[MessageContract]
public class DataTransfer
{
    [MessageHeader(MustUnderstand = true)]
    public DataContract.HandShake Handshake { get; set; }
    [MessageBodyMember(Order = 1)]
    public Stream Data { get; set; }
    //notice that it is using the default stream not a file stream, this is because the filestream you pass in has to be changed to a network stream to be sent via WCF
}

HandShake类提供了您需要与流一起包含的参数。

public SaveResponse SaveData(DataTransfer request)
{
    using (var stream = new System.IO.MemoryStream())
    {
        request.Data.CopyTo(stream);
        stream.Position = 0;
        //this is because you have less control of a stream over a network than one held locally, so by copying from the network to a local stream you then have more control

下一步是配置:您需要在服务器客户端上都进行流媒体配置。
这需要类似于以下内容的设置。
<bindings>
  <basicHttpBinding>
    <binding name="ServiceBinding" transferMode="Streamed" messageEncoding="Mtom" maxReceivedMessageSize="67108864" maxBufferSize="65536" closeTimeout="00:01:00" openTimeout="00:01:00" receiveTimeout="00:10:00" sendTimeout="00:01:00">
    </binding>
  </basicHttpBinding>
</bindings>

非常感谢!我将FileStream更改为Stream,并在客户端应用程序中添加了绑定。之后一切都开始完美地工作了。 - avidnov
您可以将流(Stream)用作参数,字符串(String)作为返回类型。您不需要为此定义消息契约(Message Contract)。 - Ykok
1
只有当整个消息都是流式数据时,才返回 "true"。如果要使用任何信息进行流传输,则需要消息;由于发送完全匿名的流可能会很危险,因此最好将有关流的某些信息(例如哈希代码、流长度等)包含在内。 - MikeT

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接