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

求助:在MVC C#表单中管理多文件上传控件的实现方法

实现表格行关联文件的Ajax批量提交方案

核心思路

将表格每行的文本数据与对应文件控件的文件打包,通过FormData对象提交到后端,要么单行独立提交,要么通过命名规则区分多行数据,让Controller能准确关联记录和附件。


前端实现步骤

1. 给表格行和控件加关联标识

为每行设置唯一ID,文件控件命名带上行索引,方便后续绑定行数据与文件:

<table>
  <tbody>
    <!-- 示例行 -->
    <tr id="row-0">
      <td><input type="text" name="title-0" placeholder="填写标题"></td>
      <td><input type="file" name="files-0" multiple></td>
      <td><button class="submit-row" data-row-index="0">提交该行</button></td>
    </tr>
    <tr id="row-1">
      <td><input type="text" name="title-1" placeholder="填写标题"></td>
      <td><input type="file" name="files-1" multiple></td>
      <td><button class="submit-row" data-row-index="1">提交该行</button></td>
    </tr>
  </tbody>
  <tfoot>
    <tr><td colspan="3"><button id="submit-all">批量提交所有行</button></td></tr>
  </tfoot>
</table>

2. 单行提交的Ajax逻辑

给每行的提交按钮绑定点击事件,收集当前行的文本数据和文件,打包成FormData发送:

// 单行提交
document.querySelectorAll('.submit-row').forEach(btn => {
  btn.addEventListener('click', function() {
    const rowIndex = this.dataset.rowIndex;
    const row = document.getElementById(`row-${rowIndex}`);
    const formData = new FormData();

    // 添加当前行的文本字段
    const titleInput = row.querySelector(`[name="title-${rowIndex}"]`);
    formData.append('Title', titleInput.value);

    // 添加当前行的所有文件
    const fileInput = row.querySelector(`[name="files-${rowIndex}"]`);
    Array.from(fileInput.files).forEach(file => {
      formData.append('Attachments', file);
    });

    // 发送请求到后端
    fetch('/YourController/SubmitSingleRow', {
      method: 'POST',
      body: formData
    })
    .then(res => res.json())
    .then(data => {
      data.success ? alert('提交成功') : alert(`提交失败:${data.msg}`);
    })
    .catch(err => console.error('请求出错:', err));
  });
});

3. 批量提交逻辑(可选)

如果需要一次性提交所有行,通过索引区分不同行的字段,打包到同一个FormData:

// 批量提交
document.getElementById('submit-all').addEventListener('click', function() {
  const formData = new FormData();
  const rows = document.querySelectorAll('tbody tr');

  rows.forEach((row, idx) => {
    // 添加行文本数据
    const title = row.querySelector(`[name="title-${idx}"]`).value;
    formData.append(`Rows[${idx}].Title`, title);

    // 添加行关联文件
    const files = row.querySelector(`[name="files-${idx}"]`).files;
    Array.from(files).forEach(file => {
      formData.append(`Rows[${idx}].Attachments`, file);
    });
  });

  fetch('/YourController/SubmitAllRows', {
    method: 'POST',
    body: formData
  })
  .then(res => res.json())
  .then(data => {
    data.success ? alert('批量提交完成') : alert(`批量提交失败:${data.msg}`);
  });
});

后端Controller处理(以.NET为例)

单行提交的Action

[HttpPost]
public IActionResult SubmitSingleRow(string Title, IEnumerable<IFormFile> Attachments)
{
  try
  {
    // 1. 保存主记录(比如到数据库)
    // 2. 处理并保存附件,关联到主记录ID
    foreach (var file in Attachments)
    {
      var savePath = Path.Combine(Directory.GetCurrentDirectory(), "wwwroot/uploads", file.FileName);
      using (var stream = new FileStream(savePath, FileMode.Create))
      {
        file.CopyTo(stream);
      }
    }
    return Json(new { success = true });
  }
  catch (Exception ex)
  {
    return Json(new { success = false, msg = ex.Message });
  }
}

批量提交的Action(需定义模型类)

先创建对应的数据模型:

public class RowDataModel
{
  public string Title { get; set; }
  public IEnumerable<IFormFile> Attachments { get; set; }
}

再编写批量处理的Action:

[HttpPost]
public IActionResult SubmitAllRows(List<RowDataModel> Rows)
{
  try
  {
    foreach (var row in Rows)
    {
      // 逐行处理记录和附件,逻辑同单行提交
    }
    return Json(new { success = true });
  }
  catch (Exception ex)
  {
    return Json(new { success = false, msg = ex.Message });
  }
}

关键注意事项

  • FormData会自动处理文件的二进制编码,无需额外转义。
  • 后端接收参数的名称必须和前端formData.append的名称完全一致。
  • 若使用其他后端语言,调整文件接收方式即可:Java用MultipartFile[],PHP用$_FILES数组解析。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.26 13:07:38