代码之家  ›  专栏  ›  技术社区  ›  Thomas

在HttpResponseMessage中返回任何不正常的结果都会导致服务器端webservice调用延迟

  •  10
  • Thomas  · 技术社区  · 8 年前

    服务器提交了一个协议冲突部分=ResponseStatusLine 客户端出错。

    经过多次测试,我可以将其简化为第一个方法“DownloadFile”是问题的起因。当我从它返回除statuscode之外的任何内容时(Content或not Content无关紧要)。

    我对这种现象完全不知所措(我本以为客户端会有问题,但服务器直到几分钟后才进入这一代码部分,看起来服务器本身就有麻烦了,这是出乎意料的,也出乎意料的是第二种方法而不是原来的方法在那里遇到了问题)。

    客户:

    WebClient webClient = new WebClient();
    webClient.QueryString.Add("downloadId", id);
    webClient.DownloadFile("localhost/Download/DownloadFile", @"c:\temp\local.txt");
    webClient = new WebClient();
    webClient.QueryString.Add("downloadId", id);
    webClient.QueryString.Add("fileLength", GetFileLength(@"c:\temp\local.txt"));
    var i = webClient.DownloadString("localhost/Download/VerifyFile");
    

    Testwise我将下载文件替换为: webClient.DownloadString("localhost/Download/DownloadFile");

    服务器:

    [RoutePrefix("Download")]
    public class DownloadController : ApiController
    {
        [HttpGet]
        [Route("DownloadFile")]
        public IHttpActionResult DownloadFile(int downloadId){
            return ResponseMessage(GetFile(downloadId));
        }
    
        private HttpResponseMessage GetFile(int downloadId){
            HttpResponseMessage result = new HttpResponseMessage(HttpStatusCode.OK);
    
            string filePath = GetFilePathFromDB(downloadid);
    
            if (filePath != String.Empty){
                var stream = new FileStream(filePath, FileMode.Open, FileAccess.ReadWrite);
                result.Content = new StreamContent(stream);
                result.Content.Headers.ContentDisposition = new ContentDispositionHeaderValue("attachment");
                result.Content.Headers.ContentDisposition.FileName = Path.GetFileName(filePath);
                result.Content.Headers.ContentType = new MediaTypeHeaderValue("application/octet-stream");
                result.Content.Headers.ContentLength = stream.Length;   
            }
            else{
                result = new HttpResponseMessage(HttpStatusCode.InternalServerError);
            }       
            return result;
        }
    
        [HttpGet]
        [Route("VerifyFile")]
        public IHttpActionResult VerifyFile(int downloadId, int fileLength)
        {
            return Content(HttpStatusCode.OK, "OK");
        }
    
    
        private string GetFilePathFromDB(int downloadId)
        {
             return @"C:\temp\mytest.txt"; // testcode
        }
    }
    
    3 回复  |  直到 8 年前
        1
  •  1
  •   Alex Terry    8 年前

    你可以试试三件事。

    1. 遵循http规范,这样就不会出现此错误

    2. 把这个加到你的客户身上web.config文件

      <system.net>
         <settings>
           <httpWebRequest useUnsafeHeaderParsing="true" />
         </settings>
      </system.net>
      
    3. class ConnectionCloseClient : WebClient
      {
          protected override WebRequest GetWebRequest(Uri address)
          {
              WebRequest request = base.GetWebRequest(address);
              if (request is HttpWebRequest)
              {
                  (request as HttpWebRequest).KeepAlive = false;
              }
              return request;
          }
      }
      
        2
  •  1
  •   gilmishal    8 年前

    我的理论是,当您从服务器收到错误响应时,文件就不会被创建。假设您正在捕获DownloadFile异常,当您返回OK以外的任何其他响应时,您应该收到该异常。

    GetFileLength可能返回一个无效的数字 answer 它会导致你提到的错误。至于为什么需要6分钟才能到达服务器代码,我想它在调用方法并返回错误之前进行了一些内部错误处理。悲哀地ASP.net4.*不是开源的,所以我不太熟悉内部工作原理。

        3
  •  1
  •   Alpha75    8 年前

    我想是因为 Keep-Alive 标题。您可以捕获http请求并检查该值。值为true将尝试保持打开的连接。并非所有代理都与此标头兼容。

    WebClient 实例并在使用下一个实例之前处理它们。或者强制标题为false。

    WebClient webClient = new WebClient();
    webClient.QueryString.Add("downloadId", id);
    webClient.DownloadFile("localhost/Download/DownloadFile", @"c:\temp\local.txt");
    webClient.Dispose();
    
    webClient2 = new WebClient();
    webClient2.QueryString.Add("downloadId", id);
    webClient2.QueryString.Add("fileLength", GetFileLength(@"c:\temp\local.txt"));
    var i = webClient2.DownloadString("localhost/Download/VerifyFile");
    webClient2.Dispose();
    

    或者用一个 using 声明:

    using (WebClient webClient = new WebClient())
    {
        webClient.QueryString.Add("downloadId", id);
        webClient.DownloadFile("localhost/Download/DownloadFile", @"c:\temp\local.txt");
    }
    
    using (WebClient webClient = new WebClient())
    {
        webClient2 = new WebClient();
        webClient2.QueryString.Add("downloadId", id);
        webClient2.QueryString.Add("fileLength", GetFileLength(@"c:\temp\local.txt"));
        var i = webClient2.DownloadString("localhost/Download/VerifyFile");
    }
    

    WebClient is opening a new connection each time I download a file and all of them stay established

    推荐文章