You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Blazor WebAssembly中InputFile标签OnChange事件失效问题

解决Blazor WebAssembly中InputFile OnChange事件不触发的问题

问题根源分析

你的代码里有两个关键问题导致InputFile的OnChange事件失效:

  1. 错误使用[StreamRendering]属性:这个属性仅针对Blazor Server或Blazor Web App的SSR/静态渲染场景设计,WebAssembly模式下完全不支持。它会改变组件的渲染逻辑,导致客户端交互事件(比如InputFile的OnChange)无法正常绑定,断点自然也命中不了。
  2. WebAssembly中非法操作服务器文件系统:代码里通过IWebHostEnvironment获取服务器路径并创建FileStream,但WebAssembly运行在浏览器沙箱中,根本没有权限直接访问服务器的文件系统,这部分代码会抛出异常,而你空的catch块又掩盖了错误,进一步导致逻辑异常。

修复步骤

  1. 移除[StreamRendering]属性:直接删掉@attribute [StreamRendering]这一行,让组件以正常的客户端交互模式渲染。
  2. 调整文件处理逻辑:
    • 如果只是要在页面展示Excel数据,可以在客户端直接解析文件(比如使用支持WASM的Excel库,如EPPlus 5+或NPOI的.NET版本)。
    • 如果需要上传到服务器,必须通过API接口将文件流发送到后端,由后端处理文件存储。
  3. 完善异常处理:给catch块添加日志或用户提示,避免错误被静默掩盖。

修正后的示例代码(客户端解析Excel并展示)

先确保你安装了支持WASM的Excel解析库,比如EPPlus:

Install-Package EPPlus -Version 5.8.1

然后修改页面代码:

@page "/weather"
@using System
@using System.IO
@using System.Collections.Generic
@using OfficeOpenXml

<PageTitle>File Upload 1</PageTitle>

<h1>Excel文件上传与预览</h1>

<p>
    <label>
        上传Excel文件:
        <InputFile OnChange="LoadFiles" accept=".xlsx,.xls" />
    </label>
</p>

@if (isLoading)
{
    <p>加载中...</p>
}
else if (excelData != null && excelData.Any())
{
    <table class="table table-striped">
        <thead>
            <tr>
                @foreach (var header in excelData.First())
                {
                    <th>@header</th>
                }
            </tr>
        </thead>
        <tbody>
            @foreach (var row in excelData.Skip(1))
            {
                <tr>
                    @foreach (var cell in row)
                    {
                        <td>@cell</td>
                    }
                </tr>
            }
        </tbody>
    </table>
}
else if (errorMessage != null)
{
    <div class="alert alert-danger">@errorMessage</div>
}

@code {
    private List<List<string>> excelData = new();
    private bool isLoading;
    private string errorMessage;

    private async Task LoadFiles(InputFileChangeEventArgs e)
    {
        isLoading = true;
        excelData.Clear();
        errorMessage = null;

        var file = e.File;
        if (!file.ContentType.Equals("application/vnd.openxmlformats-officedocument.spreadsheetml.sheet", StringComparison.OrdinalIgnoreCase) &&
            !file.ContentType.Equals("application/vnd.ms-excel", StringComparison.OrdinalIgnoreCase))
        {
            errorMessage = "请上传有效的Excel文件";
            isLoading = false;
            return;
        }

        try
        {
            await using var stream = file.OpenReadStream();
            using var package = new ExcelPackage(stream);
            var worksheet = package.Workbook.Worksheets.First();

            // 读取表头和数据
            int rowCount = worksheet.Dimension.Rows;
            int colCount = worksheet.Dimension.Columns;

            for (int row = 1; row <= rowCount; row++)
            {
                var rowData = new List<string>();
                for (int col = 1; col <= colCount; col++)
                {
                    rowData.Add(worksheet.Cells[row, col].Text ?? string.Empty);
                }
                excelData.Add(rowData);
            }
        }
        catch (Exception ex)
        {
            errorMessage = $"解析文件失败: {ex.Message}";
        }

        isLoading = false;
    }
}

补充说明(上传到服务器场景)

如果你的需求是将文件上传到服务器,需要:

  1. 在后端创建一个API接口接收文件流:
[ApiController]
[Route("api/upload")]
public class UploadController : ControllerBase
{
    private readonly IWebHostEnvironment _env;

    public UploadController(IWebHostEnvironment env)
    {
        _env = env;
    }

    [HttpPost]
    public async Task<IActionResult> Upload(IFormFile file)
    {
        if (file == null || file.Length == 0)
            return BadRequest("请选择文件");

        var uploadPath = Path.Combine(_env.WebRootPath, "uploads");
        if (!Directory.Exists(uploadPath))
            Directory.CreateDirectory(uploadPath);

        var fileName = Path.GetRandomFileName() + Path.GetExtension(file.FileName);
        var filePath = Path.Combine(uploadPath, fileName);

        await using var stream = new FileStream(filePath, FileMode.Create);
        await file.CopyToAsync(stream);

        return Ok(new { fileName = fileName, filePath = filePath });
    }
}
  1. 在Blazor页面中调用这个API上传文件:
// 替换LoadFiles方法
private async Task LoadFiles(InputFileChangeEventArgs e)
{
    isLoading = true;
    errorMessage = null;

    var file = e.File;
    var content = new MultipartFormDataContent();
    content.Add(new StreamContent(file.OpenReadStream()), "file", file.Name);

    var response = await HttpClient.PostAsync("api/upload", content);
    if (!response.IsSuccessStatusCode)
    {
        errorMessage = "上传失败";
        isLoading = false;
        return;
    }

    // 后续可以解析返回的服务器文件路径,再请求数据展示
    isLoading = false;
}

内容的提问来源于stack exchange,提问作者Arpit Sharma

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.29 07:19:56