none
[WCF]客户端上传文件流过程中网络意外断开,服务端Timeout不触发 RRS feed

  • 问题

  •  

    业务需要从客户端上传一个文件到服务端,采用WCF netTcpBinding 方式,服务端代码如下:

      private string Save(FileUploadStream fileUpload, Template t)
            {
                //aspnet_Users userInfo = GetUserInformation();
                string savePath = Path.Combine(ForecastTemplate.GetBaseUrl(), t.Id, t.Memo, "LastEditedTemplate", t.Name + "_upload.xlsx");
                string saveDir = Path.Combine(ForecastTemplate.GetBaseUrl(), t.Id, t.Memo, "LastEditedTemplate");
                if (!Directory.Exists(saveDir))
                    Directory.CreateDirectory(saveDir);
    
                if (File.Exists(savePath))
                    File.Delete(savePath);
    
                FileStream fw = new FileStream(savePath, FileMode.OpenOrCreate, FileAccess.Write);
                byte[] buffer = new byte[100];
                int length = fileUpload.ExcelStream.Read(buffer, 0, buffer.Length);
                while (length > 0)
                {
                    fw.Write(buffer, 0, length);
                    length = fileUpload.ExcelStream.Read(buffer, 0, buffer.Length);
                }
                fw.Flush();
                fw.Close();
                return savePath;
            }
        [MessageContract]
        public class FileUploadStream
        {
            private string templateId;
    
            [MessageHeader]
            public string TemplateId
            {
                get { return templateId; }
                set { templateId = value; }
            }
    
            private Stream excelStream;
    
            [MessageBodyMember]
            public Stream ExcelStream
            {
                get { return excelStream; }
                set { excelStream = value; }
            }
        }


    <system.serviceModel>
        <bindings>
          <netTcpBinding>
            <binding name="TcpBinding" closeTimeout="00:05:00" openTimeout="00:05:00" receiveTimeout="00:05:00" sendTimeout="00:05:00" transferMode="Streamed" maxBufferPoolSize="2147483647" maxBufferSize="2147483647" maxConnections="10" maxReceivedMessageSize="2147483647">
              <reliableSession enabled="false"/>
              <security mode="Transport">
                <transport clientCredentialType="Windows">
                </transport>
              </security>
              <!--<security mode="None"></security>-->
              <readerQuotas maxDepth="32" maxStringContentLength="2147483647" maxArrayLength="2147483647" maxBytesPerRead="2147483647" maxNameTableCharCount="2147483647"/>
            </binding>
          </netTcpBinding>
        </bindings>
        <services>
          <service behaviorConfiguration="ForecastTemplateBehavior" name="XXX.ForecastTemplateService">
            <endpoint address="ForecastTemplateService" binding="netTcpBinding" bindingConfiguration="TcpBinding" name="ForecastTemplateService" contract="XXX.IForecastTemplateService">
            </endpoint>
            <host>
              <baseAddresses>
                <add baseAddress="net.tcp://localhost:8100"/>
                <add baseAddress="http://localhost:8101"/>
              </baseAddresses>
              <!--<baseAddresses>
                <add baseAddress="net.tcp://localhost:8100"/>
                <add baseAddress="http://localhost:8101"/>
              </baseAddresses>-->
              <timeouts closeTimeout="00:10:00"/>
            </host>
          </service>
        </services>
        <behaviors>
          <serviceBehaviors>
            <behavior name="ForecastTemplateBehavior">
              <serviceMetadata httpGetEnabled="true" httpGetUrl="ForecastTemplateService/"/>
              <serviceDebug includeExceptionDetailInFaults="false"/>
              <serviceThrottling maxConcurrentCalls="10000" maxConcurrentSessions="10000" maxConcurrentInstances="10000"/>
              <dataContractSerializer maxItemsInObjectGraph="2147483647"/>
            </behavior>
          </serviceBehaviors>
          <endpointBehaviors>
            <behavior name="CustomBehavior">
              <dataContractSerializer maxItemsInObjectGraph="2147483647"/>
            </behavior>
          </endpointBehaviors>
        </behaviors>
      </system.serviceModel>

    在生产环境中,由于网络情况不同,当文件较大,文件流上传时客户端突然中断(比如拔掉网线),服务端程序timeout不触发,也不报任何错误,而是阻塞在

    while (length > 0)
    {
       fw.Write(buffer, 0, length);
       length = fileUpload.ExcelStream.Read(buffer, 0, buffer.Length);
    }
    这个循环的Read方法中,这就导致这个filestream 一直hold住没有办法释放,即使用户重新上传,也会因为之前的文件没有释放,导致上次的错误文件无法删除(为了保证时序性和唯一性,上传文件不能采用不同的名字),新文件不能上传。

    网上资料查了不少,依然不能解决问题,求大神告知~~

    2013年7月5日 8:06

答案

全部回复