使用.NET 4.0&上传大文件(~600MB)时出现System.OutOfMemoryException HttpClient的

时间:2016-05-02 18:42:02

标签: asp.net-web-api .net-4.0 iis-7.5 dotnet-httpclient system.net.httpwebrequest

  

我只在本地工作站和prod服务器上收到此错误。   在Dev和Cert中它工作得很好。

     

本地工作站 - 20 GB内存,Win 7 64位,IIS Express,VS   2013年开发,证书和prod - 8 GB内存,2008 R2 64位,IIS 7.5

我有一个web api(.net 4.0),它接收传入的请求正文并将其上传到存储服务器。根据{{​​3}}配置了网络API。

我在web.config中有这些

<system.webServer>
  <security>
    <requestFiltering>
      <requestLimits maxAllowedContentLength="2147483648" />
    </requestFiltering>
  </security>
</system.webServer>

<system.web>
  <httpRuntime maxRequestLength="2097152" />
</system.web>

我还有一个 IHostBufferPolicySelector 的实现,它为PUT和&amp;返回false。 POST请求。所以请求这个网络api为PUt&amp; POST没有缓冲。

任何文件&lt; ~350 MB它工作正常。但是当文件大小&gt; = ~400 MB时,web api会丢失内存异常,这只发生在本地工作站和Prod服务器上。

Web Api控制器调用代码以将请求流式传输到目标服务器

public async Task<HttpResponseMessage> StoreObjectAsync(Uri namespaceUrl, string userName, string password, string objectName, Stream objectContent, string contentType = "application/octet-stream", IDictionary<string, string> systemMetadata = null)
        {                
            Uri namespaceRootUrl = Utilities.GetNamespaceRootUrl(namespaceUrl);
            using (var request = new HttpRequestMessage() { Method = HttpMethod.Put })
            {
                request.RequestUri = Utilities.CreateRequestUri(namespaceRootUrl, objectName);

                request.Content = new StreamContent(objectContent);
                request.Content.Headers.ContentType = new MediaTypeHeaderValue(contentType);

                HttpResponseMessage response;
                response = await this.httpClient.SendAsync(request, HttpCompletionOption.ResponseHeadersRead);

                return response;
            }
        }

在网上做了一些研究之后,我从this website&amp; this link .Net 4.0上的HttpClient缓冲了请求体,并且由于这种行为,在我看来它是抛出了内存异常

因此我使用 HttpWebRequest 将我的代码更改为低于此值,我使用该控件指定该请求应该流式传输但不缓冲。

public async Task<HttpResponseMessage> StoreObjectAsync(Uri namespaceUrl, string userName, string password, string objectName, Stream content, long contentLength, string contentType = "application/octet-stream", IDictionary<string, string> systemMetadata = null)
        {            

            Uri namespaceRootUrl = Utilities.GetHCPNamespaceRootUrl(namespaceUrl);

            HttpWebRequest httpWebRequest = ((HttpWebRequest)WebRequest.Create(requestUri));           

            httpWebRequest.Method = "PUT";
            httpWebRequest.KeepAlive = true;

            httpWebRequest.AllowWriteStreamBuffering = false;
            httpWebRequest.ContentType = contentType;
            httpWebRequest.ContentLength = contentLength;


            using (Stream requestStream = await httpWebRequest.GetRequestStreamAsync())
            {
                await content.CopyToAsync(requestStream);
            }

            var webResponse = await httpWebRequest.GetResponseAsync();
            HttpWebResponse httpWebResponse = (HttpWebResponse)webResponse;
            Stream httpWebResponseContent = httpWebResponse.GetResponseStream();

            HttpResponseMessage response = new HttpResponseMessage()
            {
                StatusCode = httpWebResponse.StatusCode,
                ReasonPhrase = httpWebResponse.StatusDescription,
                Content = new StreamContent(httpWebResponseContent)
            };

            return response;
        }

现在它在我的本地机器上工作正常。我能够上传大约1GB的文件,没有任何错误或内存异常。还没把它推到Prod。

但我仍然不明白为什么在.net 4.0上使用HttpClient的相同代码适用于Dev和Cert服务器,但不适用于Prod和我的本地。

请帮助我理解

  

如何找出它在Dev和Cert上运作的原因?
什么系统/服务器   配置会影响这个API的内存分配吗?

0 个答案:

没有答案