5

System.Net.Http.HttpClientより大きなファイル (+1GB) を POST するために使用しようとしましたが、SystemOutOfMemory例外がスローされます:

at System.Net.ScatterGatherBuffers.AllocateMemoryChunk(Int32 newSize)
at System.Net.ScatterGatherBuffers..ctor(Int64 totalSize)
at System.Net.ConnectStream.EnableWriteBuffering()
at System.Net.HttpWebRequest.SetRequestSubmitDone(ConnectStream submitStream)
at System.Net.Connection.CompleteStartRequest(Boolean onSubmitThread, HttpWebRequest request, TriState needReConnect)
at System.Net.Connection.SubmitRequest(HttpWebRequest request, Boolean forcedsubmit)
at System.Net.ServicePoint.SubmitRequest(HttpWebRequest request, String connName)
at System.Net.HttpWebRequest.SubmitRequest(ServicePoint servicePoint)
at System.Net.HttpWebRequest.BeginGetRequestStream(AsyncCallback callback, Object state)
at System.Net.Http.HttpClientHandler.StartGettingRequestStream(RequestState state)
at System.Net.Http.HttpClientHandler.PrepareAndStartContentUpload(RequestState state)

どうやら、HttpWebRequestここで説明されているように、同様の問題が発生するようです: http://support.microsoft.com/kb/908573

AllowWriteStreamBuffering基になる Web リクエストをに設定する方法はありますfalseか? 何も見つかりません。

乾杯、

4

4 に答える 4

5

興味のある他の人の時間を節約するために、私は自分の質問に答えています。

いくつかのテストの後、例外HttpWebRequestは質問で説明したのと同じ問題に起因しているようです。Microsoft.AspNet.WebApi バージョン 4.0.20710.0 を使用しています。

以下に 2 つの同等のコードを示します。前者は大きなファイルで失敗しますが、後者は問題なく動作します。

ところで、問題にもかかわらず、の全体的な利点がHttpClient本当に明らかになります:-)


使用してHttpClient

var clientRef = new System.Net.Http.HttpClient(
    new HttpClientHandler()
    {
        Credentials = new System.Net.NetworkCredential(MyUsername, MyPassword)
    });
clientRef.BaseAddress = new Uri(serverAddress);
clientRef.DefaultRequestHeaders.ExpectContinue = false;
clientRef.PostAsync(
    MyFavoriteURL,
    new System.Net.Http.StreamContent(inputStream)).ContinueWith(
        requestTask =>
        {
            HttpResponseMessage response = requestTask.Result;
            response.EnsureSuccessStatusCode();
        }, TaskContinuationOptions.LongRunning).Wait();

使用してHttpWebRequest

// Preauthenticate
var req  = (System.Net.HttpWebRequest)System.Net.HttpWebRequest.Create(MyFavoriteURL);
req.Credentials = new System.Net.NetworkCredential(MyUsername, MyPassword);
req.Method = "POST";
req.PreAuthenticate = true;
req.Timeout = 10000;
using (var resp = (System.Net.HttpWebResponse)req.GetResponse())
{
     if (resp.StatusCode != System.Net.HttpStatusCode.Accepted && resp.StatusCode != System.Net.HttpStatusCode.OK)
     {
         throw new Exception("Authentication error");
     }
}

// Upload
req = (System.Net.HttpWebRequest)System.Net.HttpWebRequest.Create(MyFavoriteURL);
req.Credentials = new System.Net.NetworkCredential(MyUsername, MyPassword);
req.Method = "POST";
req.PreAuthenticate = true;
req.Timeout = 1200000;
req.ContentLength = inputStream.Length;
req.ContentType = "application/binary";
req.AllowWriteStreamBuffering = false;
req.Headers.ExpectContinue = false;
using (var reqStream = req.GetRequestStream())
{
    inputStream.CopyTo(reqStream);
}

using (var resp = (System.Net.HttpWebResponse)req.GetResponse())
{
    if (resp.StatusCode != System.Net.HttpStatusCode.Accepted && resp.StatusCode != System.Net.HttpStatusCode.OK)
    {
        throw new Exception("Error uploading document");
    }
}
于 2013-04-19T21:34:26.277 に答える
0

大きなファイルのアップロードでも同じ問題に遭遇しました。誰かを助けるために私の発見を追加します。

HttpClient は、次の条件に基づいてバッファリングを行うかどうかを決定します。

if( HttpRequestMessage.Headers.TransferEncodingChunked == true ||     HttpRequestMessage.Content.Headers.ContentLength != null )
{
  //do streamed upload
}else
{
  //do buffered upload.
}

サーバーはリクエストごとに最大 150 MB を受け入れるため、PushedStreamContent を HttpRequestMessage.Content として使用しました。TransferEncodingChunked を True に設定すると、メモリ スパイクが減少します。

于 2016-03-18T12:30:22.270 に答える
0

ヘッダーが重複していると思います。前者を削除できます

req.Headers.Add("ExpectContinue", "false");
...
req.Headers.ExpectContinue = false;
于 2016-07-20T16:22:26.413 に答える