System.IO.IOException: Unexpected end of stream.
at Microsoft.AspNetCore.WebUtilities.MultipartReaderStream.<ReadAsync>d__32.MoveNext()
--- End of stack trace from previous location where exception was thrown ---
at System.Runtime.CompilerServices.TaskAwaiter.ThrowForNonSuccess(Task task)
at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task)
at Microsoft.AspNetCore.WebUtilities.StreamHelperExtensions.<DrainAsync>d__2.MoveNext()
--- End of stack trace from previous location where exception was thrown ---
at System.Runtime.CompilerServices.TaskAwaiter.ThrowForNonSuccess(Task task)
at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task)
at Microsoft.AspNetCore.WebUtilities.MultipartReader.<ReadNextSectionAsync>d__14.MoveNext()
--- End of stack trace from previous location where exception was thrown ---
at System.Runtime.CompilerServices.TaskAwaiter.ThrowForNonSuccess(Task task)
at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task)
at System.Runtime.CompilerServices.TaskAwaiter`1.GetResult()
at AspNetCoreFileUpload.Controllers.FileUploadController.<Index>d__0.MoveNext()
in C:\\GitHub\\StackOverflow\\LargeFileUploadController\\FileUploadController.cs:line 29
Repro: https://github.com/bigfont/StackOverflow/tree/master/LargeFileUploadController
Form
<form action = ""/FileUpload"" method=""post"" enctype=""multipart/form-data"">
<label for=""myfile1"">File</label>
<input type=""file"" name=""myFile1"" />
<label for=""myfile2"">File</label>
<input type=""file"" name=""myFile2"" />
<input type=""submit"" value=""Send"" />
</form>
Controller
public class FileUploadController : Controller
{
[HttpPost]
public async Task<IActionResult> Index()
{
var boundary = GetBoundary(Request.ContentType);
var reader = new MultipartReader(boundary, Request.Body);
try
{
var section = await reader.ReadNextSectionAsync();
}
catch (System.Exception ex)
{
return new OkObjectResult(new { ex = ex.ToString() });
}
return new OkObjectResult(new { message = "Done" });
}
private static string GetBoundary(string contentType)
{
var elements = contentType.Split(' ');
var element = elements.Where(entry => entry.StartsWith("boundary=")).First();
var boundary = element.Substring("boundary=".Length);
// Remove quotes
if (boundary.Length >= 2 &&
boundary[0] == '"' && boundary[boundary.Length - 1] == '"')
{
boundary = boundary.Substring(1, boundary.Length - 2);
}
return boundary;
}
}
I got almost the same exception recently. I'm saying almost because they actually renamed the exception to Unexpected end of Stream, the content may have already been read by another component., which actually means that something already consumed the body stream. The comments of the following change gives us the understanding of what's happening:
Tratcher commented on Mar 23
...The MVC model binder reads the form and buffers the multipart segments for you, so there's no point in re-parsing request body with the MultipartReader...
So, the question is how to disable the default form binding (reading the request form)?
I found the DisableFormValueModelBindingAttribute attribute in this Mvc.FileUpload sample which disables the form binding and this is what it looks like:
[AttributeUsage(AttributeTargets.Class | AttributeTargets.Method, AllowMultiple = false, Inherited = true)]
public class DisableFormValueModelBindingAttribute : Attribute, IResourceFilter
{
public void OnResourceExecuting(ResourceExecutingContext context)
{
var formValueProviderFactory = context.ValueProviderFactories
.OfType<FormValueProviderFactory>()
.FirstOrDefault();
if (formValueProviderFactory != null)
{
context.ValueProviderFactories.Remove(formValueProviderFactory);
}
var jqueryFormValueProviderFactory = context.ValueProviderFactories
.OfType<JQueryFormValueProviderFactory>()
.FirstOrDefault();
if (jqueryFormValueProviderFactory != null)
{
context.ValueProviderFactories.Remove(jqueryFormValueProviderFactory);
}
}
public void OnResourceExecuted(ResourceExecutedContext context)
{
}
}
If you want some more information, you can check out the following:
Just for info - as commented before, the MVC model binder reads the form, but where can one find the results. The results can be found in the HttpRequest.Form, which has Files.
Don't know if this might help you but I came across simular issue "Unexpected end of Stream, the content may have already been read by another component".
app.Use(async (context, next) => {
context.Request.EnableRewind();
await next();
});
Code above were added in Startup.cs Configure method.
Hope it helps
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