I'm trying to upload very large files (>2GB) to my WebAPI application (Running on .NET 4.5.2, Windows 2012R2).
Setting the httpRuntime maxRequestLength property is of no use because it's only working with files smaller than 2GB.
I'm currently using a custom MultipartFormDataStreamProvider to read the entire stream on the Server and I've already turned off buffering using a custom WebHostBufferPolicySelector.
What I discovered is that ASP.NET (or WebAPI for that matter) uses a HttpBufferlessInputStream under the Hood which has a field called _disableMaxRequestLength. If I set this value to to true (via reflection), I can stream files of any size.
However, fiddling around these with these internas is clearly not a good way.
The HttpRequest class used for the request has a method called GetBufferlessInputStream which has an overload that allows to disable the maxRequestLength.
My question is: How can I get the WebAPI to use this overload instead of the Standard one?
Is there any way to replace the Default HttpRequest or HttpContext class? Or do I really Need to use reflection for the whole stuff?
This is the code I'm currently using to disable the maxRequestLength:
private void DisableRequestLengthOnStream(HttpContent parent) { var streamContentProperty = parent.GetType().GetProperty("StreamContent", BindingFlags.Instance | BindingFlags.NonPublic | BindingFlags.Public); if (streamContentProperty == null) return; var streamContent = streamContentProperty.GetValue(parent, null); if (streamContent == null) return; var contentProperty = typeof(StreamContent).GetField("content", BindingFlags.Instance | BindingFlags.NonPublic); if (contentProperty == null) return; var content = contentProperty.GetValue(streamContent); if (content == null) return; var requestLengthField = content.GetType().GetField("_disableMaxRequestLength", BindingFlags.Instance | BindingFlags.NonPublic); if (requestLengthField == null) return; requestLengthField.SetValue(content, true); }
Ok, I found a pretty simple solution. The answer from @JustinR. would work, of course. But I wanted to continue to use a MultipartFormDataStreamProvider because that handles all the MIME stuff.
The solution is to simply create a new StreamContent instance with the correct bufferless Input stream and populate it with the headers from the original Content:
var provider = new MultipartFormDataStreamProvider(path); var content = new StreamContent(HttpContext.Current.Request.GetBufferlessInputStream(true)); foreach (var header in Request.Content.Headers) { content.Headers.TryAddWithoutValidation(header.Key, header.Value); } await content.ReadAsMultipartAsync(provider);
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