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

循环中批量上传文件仅首个生效问题排查及代码求助

循环上传文件仅第一条生效的问题排查与修复

问题现象

在项目中通过循环为每条记录生成文件上传控件,只有第一条记录的文件能成功上传,其余记录无法完成上传操作。

核心原因

HTML页面中元素ID必须唯一,但你的Razor视图在循环时重复生成了固定ID的元素(如btnUpLoad、mostanadPath、spnImageCartMlie、divmessage),导致DOM只能识别第一个匹配的元素,后续记录的上传按钮无法关联到对应的文件控件。

修复方案

1. 修改Razor视图代码(动态生成唯一ID)

将循环内的固定ID改为带索引的动态ID,并在调用UploadImage时传入当前行的索引,确保每个上传按钮能关联到对应行的文件控件:

<form asp-controller="Tax" asp-action="SabtEditTaxParvanedAsync" method="post" enctype="multipart/form-data">
    <div class="container-fluid" style="overflow: auto; overflow-x: hidden; direction:ltr ">
        <table class="table table-bordered table-striped table-hover display" width="100%" style="direction:rtl;font-size:12px">
            <thead>
                <tr class="table-head-blue text-center" style="background-color: #416992; color: white; position: sticky; top: 0;">
                    <th style="width:150px">وضعیت</th>
                    <th>پروسه پرونده</th>
                    <th>مستندات</th>
                    <th>تاریخ</th>
                </tr>
            </thead>
            @{ var count = 0;}
            @for (var i = 0; i < Model.Count(); i++)
            {
                <tr>
                    <td style="width:150px">
                        <label class="switch">
                            <input type="checkbox" onchange="DisableRow(this)" asp-for="@Model.ToList()[i].state" value="True">
                            <span class="slider round"></span>
                        </label>
                    </td>
                    <td style="font-size: 12px">
                        <span>@Model.ToList()[i].prosessName</span>
                        <input class="d-none" value="@Model.ToList()[i].prosessName" name="[@i].prosessName" />
                    </td>
                    <td>
                        <div class="d-flex justify-content-around">
                            <div>
                                <span class="text-center mt-2" id="spnImageCartMlie_@i" style="color: black;font-size: 12px"></span>
                            </div>
                            <div>
                                <!-- 传入当前索引到UploadImage函数 -->
                                <input type="button" onclick="UploadImage(@i)" value="Upload" class="btn btn-outline-danger " id="btnUpLoad_@i" />
                                <div id="divmessage_@i" class="text-center hidden m-2"></div>
                            </div>
                            <!-- 动态生成唯一ID -->
                            <input id="mostanadPath_@i" name="[@i].prosessMastand" type="file" class="">
                        </div>
                    </td>
                    <td style="font-size: 12px" hidden>
                        <span>@Model.ToList()[i].prosessId</span>
                        <input class="d-none" value="@Model.ToList()[i].prosessId" name="[@i].prosessId" />
                    </td>
                    <td></td>
                </tr>
                count++;
            }
        </table>
    </div>
    <div class="text-center">
        <button class="btn btn-success col-4 mb-2 " type="submit">ثبت اطلاعات</button>
    </div>
</form>

2. 调整UploadImage JavaScript函数

修改函数逻辑,通过传入的索引找到对应行的文件控件和提示元素:

function UploadImage(index) {
    // 根据索引获取当前行的文件控件
    var fileInput = document.getElementById(`mostanadPath_${index}`);
    var messageDiv = document.getElementById(`divmessage_${index}`);
    var imageSpan = document.getElementById(`spnImageCartMlie_${index}`);

    if (fileInput.files.length === 0) {
        messageDiv.textContent = "请选择文件";
        messageDiv.classList.remove("hidden");
        return;
    }

    // 这里可以添加文件预览或Ajax上传逻辑
    // 如果是通过表单整体提交,此函数可仅做文件校验
    messageDiv.textContent = "";
    messageDiv.classList.add("hidden");
    imageSpan.textContent = fileInput.files[0].name;
}

3. 后端Action代码优化(避免空引用异常)

在处理文件时,先判断prosessMastand是否为空,避免空引用错误:

[HttpPost]
public async Task<IActionResult> SabtEditTaxParvanedAsync([FromForm]IEnumerable<TaxParvande> taxParvandes)
{
    if (taxParvandes == null)
    {
        return Content("未选择任何记录");
    }
    foreach (var item in taxParvandes)
    {
        // 新增判断:跳过无文件的记录
        if (item.prosessMastand == null || item.prosessMastand.Length == 0)
        {
            continue;
        }

        var fileName = Path.GetFileName(item.prosessMastand.FileName);
        // 建议拼接唯一文件名,避免覆盖
        var uniqueFileName = $"{Guid.NewGuid()}_{fileName}";
        var path = Path.Combine(_webHostEnvironment.WebRootPath, "ListUpload", uniqueFileName);
        
        using (FileStream stream = new FileStream(path, FileMode.Create))
        {
            await item.prosessMastand.CopyToAsync(stream);
            // using块会自动关闭流,无需手动调用Close()
        }

        var taxparvand = new TaxParvande
        {
            prosessId = item.prosessId,
            prosessName = item.prosessName,
            state = item.state,                    
            FilePath = path,
        };
        _context.Add(taxparvand);
        await _context.SaveChangesAsync();
    }
    return View();
}

额外说明

  • 表单提交时,Razor生成的name="[@i].prosessMastand"格式是正确的,ASP.NET Core可以正确绑定到IEnumerable<TaxParvande>集合。
  • 建议为上传文件生成唯一文件名(如拼接Guid),避免同名文件覆盖问题。
  • 确保表单添加了enctype="multipart/form-data"属性,这是文件上传的必要条件。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.14 02:05:25