Uploading files in Blazor is a unique challenge, because each Blazor mode (SSR, Server, Wasm) requires a different approach. There is no interactivity in Blazor SSR, so the entire form (including file fields) must be processed all at once on the server.
Code Behind
In code behind you just need to use the IFormFile
type for the property that represents the uploaded file.
public partial class Profile
{
[SupplyParameterFromForm] private ProfileForm Form { get; set; } = new ();
}
public class ProfileForm
{
public string Description { get; set; }
public IFormFile File { get; set; }
}
Form in UI
The source of errors and long debugging sessions is usually in the UI. In the form, you need to follow these two important rules:
- the form must have
enctype="multipart/form-data"
-
InputFile
component should not use two-way binding, only thename
attribute
An example might look like this:
<EditForm OnSubmit="OnSubmit" Model="Form" FormName="profile" enctype="multipart/form-data">
<DataAnnotationsValidator/>
<div class="form-group">
<label for="file">File</label>
<InputFile id="file" class="form-control" name="Form.File"/>
</div>
<InputText type="hidden" @bind-Value="Form.Description"/>
<br/>
<button class="btn btn-primary">Odeslat</button>
</EditForm>
Form processing
To handle the upload, you just need to implement the OnSubmit
method. In most of my apps, I use Azure Storage, but for simplicity, this example shows how to work directly with the file.
private async Task OnSubmit(EditContext ctx)
{
await using var str = new FileStream("/Users/mholec/Temporary/" + Form.File.FileName, FileMode.Create);
await Form.File.CopyToAsync(str);
}
Alternative solution
Instead of working with IFormFile
, you could also access the uploaded file directly through HttpRequest
. You can get it from HttpContext
, which can be passed to the component as a cascading parameter (not via injection).
public partial class Profile
{
[SupplyParameterFromForm] private ProfileForm Form { get; set; } = new ();
[CascadingParameter] private HttpContext Context { get; set; }
}
This approach is useful when working with multiple files or large files. It gives the developer more flexibility when handling the data stream. You can learn more about uploading large files in the
documentation.
Finally, I'd like to mention that instead of using <EditForm>
, you can use a plain <form>
and rely only on the name
attribute for form fields. However, you'll lose two-way binding and validation support. If you choose this approach, don't forget to include the antiforgery token.
<form>
<AntiforgeryToken/>
</form>
For clarity, note that the new antiforgery middleware must always be placed after the authentication and authorization middlewares in the pipeline. So make sure the order in your Program.cs
looks like this:
app.UseAuthentication();
app.UseAuthorization();
app.UseAntiforgery();
Top comments (0)