I've been trying to use System.Net.Http.HttpClient
to POST a larger file (+1GB) but it throws a SystemOutOfMemory
exception:
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)
Apparently, a similar problem occurs for HttpWebRequest
as discussed here: http://support.microsoft.com/kb/908573.
Is there any way to set AllowWriteStreamBuffering
of the underlying web request to false
? I can't find any.
Cheers,
NET 6, the WebRequest, WebClient, and ServicePoint classes are deprecated. The classes are still available, but they're not recommended for new development.
In a nutshell, WebRequest—in its HTTP-specific implementation, HttpWebRequest—represents the original way to consume HTTP requests in . NET Framework. WebClient provides a simple but limited wrapper around HttpWebRequest.
Provides a programming interface for modern HTTP applications, including HTTP client components that allow applications to consume web services over HTTP and HTTP components that can be used by both clients and servers for parsing HTTP headers. Commonly Used Types: System.
The HttpWebRequest class provides support for the properties and methods defined in WebRequest and for additional properties and methods that enable the user to interact directly with servers using HTTP.
Just to save time of others interested, I'm answering my own question.
After a few tests the exception seems to be down to the same issue with HttpWebRequest
as discussed in the question. I use Microsoft.AspNet.WebApi version 4.0.20710.0.
Below are two equivalent pieces of code; the former fails on large files, whereas the latter works fine.
BTW, despite the issue overall benefits of the HttpClient
become really apparent :-)
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");
}
}
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With