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

Modal复用InputFile组件上传文件时触发JSInterop异常求助

问题描述

抛出异常:Microsoft.JSInterop.JSException: There is no file with ID 6. The file list may have changed. Error: There is no file with ID 6

触发场景:打开包含两个InputFile的模态框,关闭后重新打开,在其中一个InputFile上传文件时触发该错误。两个InputFile分别位于独立的ProductImageUploaderComponent组件中。

模态框代码:

<div class="product-portrait-container">
    <div class="product-portrait-image-container">
        <p>@Localize["Product_Background_Image"]</p>

        <div class="product-image-div">
            <ProductImageUploaderComponent @ref="_backgroundImageUploader"
                                            IsPortrait="_isPortrait"
                                            NotifyParent="NotifyProductCreationModal"
                                            AllowedFileExtensions="@Constants.ALLOWED_PRODUCT_IMAGE_FILE_EXTENSIONS"
                                            IsEditMode="@_isEditMode"></ProductImageUploaderComponent>
        </div>
    </div>

    <div class="product-portrait-image-container">
        <p>@Localize["Product_Image_Foreground"]</p>

        <div class="product-image-div">
            <ProductImageUploaderComponent @ref="_imageForegroundUploader"
                                           IsPortrait="_isPortrait"
                                           NotifyParent="NotifyProductCreationModal"
                                           AllowedFileExtensions="@allowedImageForegroundFileExtension"
                                           IsEditMode="@_isEditMode"></ProductImageUploaderComponent>
        </div>
    </div>
</div>

ProductImageUploaderComponent核心代码:

<InputFile id="@($"fileInput{ComponentId}")"
            type="file"
            name="file"
            accept="@AllowedFileExtensions"
            style="display: none"
            @ref="InputFile"
            OnChange="UploadImage" />
解决方案

1. 用条件渲染销毁/重建模态框组件

避免用CSS隐藏模态框(比如display: none),改用@if条件渲染控制模态框的存在:

@if (_showModal)
{
    <!-- 模态框内容 -->
    <div class="product-portrait-container">
        <!-- ... 原有组件代码 ... -->
    </div>
}

关闭模态框时设置_showModal = false,这样内部的ProductImageUploaderComponent会被彻底销毁,重新打开时会创建全新实例,避免旧的InputFile引用残留。

2. 在组件销毁时清理InputFile状态

让ProductImageUploaderComponent实现IDisposable接口,清理InputFile引用并重置文件输入:

public class ProductImageUploaderComponent : ComponentBase, IDisposable
{
    private ElementReference _inputFile;
    [Inject] private IJSRuntime JSRuntime { get; set; }

    // ... 其他属性和方法 ...

    public void Dispose()
    {
        // 清空文件输入的value,避免残留旧文件ID
        _ = JSRuntime.InvokeVoidAsync("clearFileInput", _inputFile);
    }
}

在全局JS文件中添加clearFileInput函数:

function clearFileInput(element) {
    element.value = '';
}

3. 确保ComponentId全局唯一

每次创建ProductImageUploaderComponent时生成新的ComponentId,避免重复ID导致JS元素选择冲突:

public class ProductImageUploaderComponent : ComponentBase
{
    public string ComponentId { get; set; } = Guid.NewGuid().ToString("N");

    // ... 其他代码 ...
}

4. 重置InputFile引用和上传状态

在ProductImageUploaderComponent的OnParametersSetAsync方法中重置上传相关状态,确保组件重新激活时状态干净:

protected override async Task OnParametersSetAsync()
{
    await base.OnParametersSetAsync();
    // 清空文件输入
    if (_inputFile.Context != null)
    {
        await JSRuntime.InvokeVoidAsync("clearFileInput", _inputFile);
    }
    // 重置其他上传状态(比如已选文件、上传进度等)
    _selectedFile = null;
    _uploadProgress = 0;
}
关键原因分析

这个错误本质是Blazor的InputFile组件依赖JS维护的文件列表,当模态框关闭后组件未被销毁,重新打开时旧的组件实例引用依然存在,JS侧的文件列表已被清空,但Blazor侧仍尝试引用旧的文件ID,导致不匹配。通过销毁组件、重置状态、确保唯一ID,可以彻底解决这个问题。

内容的提问来源于stack exchange,提问作者Arnaud VDR

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.16 07:20:19