Hi @ardalis I've been trying to get file stream working in .NET Core MVC using information from: Docs/aspnetcore/mvc/models/file-uploads/sample/FileUploadSample/
But with no success in a pure .Net Core (1.1) MVC (as the sample for streaming uses Angular bindings, which is not what I'm using).
This Test File Streaming Repo contains the bare minimum code to reproduce the issue I've received.
The user navigates to TestFileUpload/Views/Streaming/Index.cshtml they will enter some details and select the file to upload. The user will then submit the form;
<form asp-area="" enctype="multipart/form-data" asp-controller="Streaming" asp-action="StreamUpload" asp-route-returnurl="@ViewData[ "ReturnUrl" ]" id="submit-file-form" method="post">
<input name="CurriculumVitae" type="file" id="file" />
<button type="submit">Create User</button>
</form>
The form then calls within: TestFileUpload/Controllers/StreamingController.cs
public async Task< IActionResult > StreamUpload() {
...
var reader = new MultipartReader( boundary, HttpContext.Request.Body );
var section = await reader.ReadNextSectionAsync();
...
}
But, I then receive the error "IOException: Unexpected end of Stream, the content may have already been read by another component."
TestFileUpload.Controllers.StreamingController+<StreamUpload>d__2.MoveNext() in StreamingController.cs
51. var section = await reader.ReadNextSectionAsync();
I've even tried changing csproj to use Net 4.6.2 but with no success;
<PropertyGroup>
<TargetFrameworks>netcoreapp1.1;net462</TargetFrameworks>
</PropertyGroup>
<PropertyGroup>
<PackageTargetFallback>$(PackageTargetFallback);portable-net462+win8+wp8+wpa81;</PackageTargetFallback>
</PropertyGroup>
I spent some time troubleshooting this and was able to figure out the issue. The docs sample does use Angular, and one key reason is described here:
// 2. Typically antiforgery tokens are sent in request body, but since we
// do not want to read the request body early, the tokens are made to be
// sent via headers. The antiforgery token filter first looks for tokens
// in the request header and then falls back to reading the body.
[HttpPost]
[DisableFormValueModelBinding]
[ValidateAntiForgeryToken]
public async Task<IActionResult> Upload()
Angular's code is used to pass the anti-forgery token in an HTTP header. In your sample, you're just doing a straight form post from the browser, so no headers are being set. Likewise, the antiforgery token isn't present in the form values, either. Thus, the request is failing. The error message isn't helpful, and I'm not sure why that is, but if you remove the [ValidateAntiForgeryToken]
attribute, I suspect you'll find your sample works fine (it does for me).
Thanks so much Steve, looks like its working well.
Got the same issue, it works if i don't move to the next multipart section before using the stream ... but it's not what i want to do ... i need some other data from the multipart form before processing the stream ...
(i don't have an anti forgery token)
Most helpful comment
I spent some time troubleshooting this and was able to figure out the issue. The docs sample does use Angular, and one key reason is described here:
Angular's code is used to pass the anti-forgery token in an HTTP header. In your sample, you're just doing a straight form post from the browser, so no headers are being set. Likewise, the antiforgery token isn't present in the form values, either. Thus, the request is failing. The error message isn't helpful, and I'm not sure why that is, but if you remove the
[ValidateAntiForgeryToken]
attribute, I suspect you'll find your sample works fine (it does for me).