diff --git a/aspnetcore/mvc/models/file-uploads.md b/aspnetcore/mvc/models/file-uploads.md index 307dfbf0d9fd..f228c95b15de 100644 --- a/aspnetcore/mvc/models/file-uploads.md +++ b/aspnetcore/mvc/models/file-uploads.md @@ -415,6 +415,47 @@ The preceding example is similar to a scenario demonstrated in the sample app: ### Upload large files with streaming +For scenarios where large file uploads are required, streaming uploads allow you to process incoming multipart form data directly without buffering the entire file in memory or on disk via model binding. This technique is especially important for files that could exceed server or framework buffering thresholds. + +The [sample application for 9.x](https://github.com/dotnet/AspNetCore.Docs/tree/main/aspnetcore/mvc/models/file-uploads/samples/9.x/FileManagerSample) demonstrates how a server can receive a file and stream the data directly to disk, supporting robust cancellation via the HTTP request's cancellation token. + + is an ASP.NET Core utility for reading files from incoming requests. The following snippet shows how to process a request and stream the file into an `outputStream` (such as a ): + +```csharp +// Read the boundary from the Content-Type header +var boundary = HeaderUtilities.RemoveQuotes( + MediaTypeHeaderValue.Parse(request.ContentType).Boundary).Value; + +// Use MultipartReader to stream data to a destination +var reader = new MultipartReader(boundary, Request.Body); +MultipartSection? section; + +while ((section = await reader.ReadNextSectionAsync(cancellationToken)) != null) +{ + var contentDisposition = section.GetContentDispositionHeader(); + + if (contentDisposition != null && contentDisposition.IsFileDisposition()) + { + await section.Body.CopyToAsync(outputStream, cancellationToken); + } +} +``` + + is a wrapper around that doesn't require you to write manual request body parsing code. You can use its method to populate the request's form data, then access uploaded files from the built-in collection: + +```csharp +// Get the IFormFeature and read the form +var formFeature = Request.HttpContext.Features.GetRequiredFeature(); +await formFeature.ReadFormAsync(cancellationToken); + +// Access the uploaded file (example: first file) +var filePath = Request.Form.Files.First().FileName; + +return Results.Ok($"Saved file at {filePath}"); +``` + +For advanced scenarios, manually parse the raw request body using , which exposes an [`IPipeReader`](/aspnet/core/fundamentals/middleware/request-response) for low-level, high-performance streaming. The sample app includes endpoint handlers that use `IPipeReader` in both minimal APIs and controllers. + The [3.1 example](https://github.com/dotnet/AspNetCore.Docs/blob/main/aspnetcore/mvc/models/file-uploads/samples/3.x/SampleApp/Pages/StreamedSingleFileUploadDb.cshtml) demonstrates how to use JavaScript to stream a file to a controller action. The file's antiforgery token is generated using a custom filter attribute and passed to the client HTTP headers instead of in the request body. Because the action method processes the uploaded data directly, form model binding is disabled by another custom filter. Within the action, the form's contents are read using a `MultipartReader`, which reads each individual `MultipartSection`, processing the file or storing the contents as appropriate. After the multipart sections are read, the action performs its own model binding. The initial page response loads the form and saves an antiforgery token in a cookie (via the `GenerateAntiforgeryTokenCookieAttribute` attribute). The attribute uses ASP.NET Core's built-in [antiforgery support](xref:security/anti-request-forgery) to set a cookie with a request token: