如何将复选框选中项传递至ASP.NET Core MVC控制器?
问题描述
需要将复选框选中的文件路径信息发送至ASP.NET Core MVC控制器,当前参数会被拼接到URL中,无法正确传递到DownloadAll方法。预期传递FullFolderPath参数和选中项的FullFilePath数组。
现有视图代码
<form> <input type="hidden" name="FullFilePath" value="@Model[0].FullFilePath"> <input type="hidden" name="FullFolderPath" value="@Model[0].FullFolderPath"> <table id="myTable" class="table CustomColorTable" border="1"> <thead> <tr> <th> <div class="icon icon-shape bg-indigo text-white rounded-circle shadow"> <i class="bi bi-folder2"></i> </div> <div>Select All</div> </th> <th> <div class="icon icon-shape bg-indigo text-white rounded-circle shadow"> <i class="bi bi-folder2"></i> </div> <div>Folder Name</div> </th> <th> <div class="icon icon-shape bg-indigo text-white rounded-circle shadow"> <i class="bi bi-file-earmark-text"></i> </div> <div>File Name</div> </th> <th> <div class="icon icon-shape bg-indigo text-white rounded-circle shadow"> <i class="bi bi-calendar2-check"></i> </div> <div>Date Modified</div> </th> </tr> </thead> <tbody> @foreach (var item in Model) { <tr class="header"> <td> <div> <input type="checkbox" name="@item.FullFilePath" id="@item.FullFilePath"> </div> </td> <td> @Html.DisplayFor(modelItem => item.FolderName) </td> <td> @Html.DisplayFor(modelItem => item.FileName) </td> <td> @Html.DisplayFor(modelItem => item.DateModified) </td> </tr> } </tbody> </table> <button id="btnSubmit" class="btnClick" asp-controller="Directory" asp-action="DownloadAll">Download Selected Items</button> </form>
填充视图的控制器方法
public IActionResult GetFiles(string fullfolderPath) { // 获取文件夹中的所有文件 string[] filePaths = Directory.GetFiles(fullfolderPath); // 将文件信息复制到Model集合 List<FileViewModel> files = new List<FileViewModel>(); foreach (string filePath in filePaths) { files.Add(new FileViewModel { FileName = Path.GetFileName(filePath), FolderName = Path.GetFileName(Path.GetDirectoryName(filePath)), FullFilePath = filePath, DateModified = new FileInfo(filePath).LastWriteTime, FileCount = Directory.GetFiles(fullfolderPath).Length, FullFolderPath = fullfolderPath, }); } return View(files); }
接收参数的控制器方法
[HttpPost] public IActionResult DownLoadAll(string FullFolderPath, string[] FullfilePath) { if (FullFolderPath == null) { return View(); } // 获取文件夹下所有文件路径(注:此处应该使用传入的选中文件路径) string[] filePaths = Directory.GetFiles(FullFolderPath); var zipName = $"TestFiles-{DateTime.Now.ToString("yyyy_MM_dd-HH_mm_ss")}.zip"; using (MemoryStream ms = new MemoryStream()) { // 需要引用:using System.IO.Compression; using (var zip = new ZipArchive(ms, ZipArchiveMode.Create, true)) { // 遍历文件夹所有文件(注:应改为遍历选中的文件) foreach (string filePath in filePaths) { var entry = zip.CreateEntry(Path.GetFileName(filePath)); using (var fileStream = new MemoryStream(filePath.Length)) using (var entryStream = entry.Open()) { fileStream.CopyTo(entryStream); } }; } return File(ms.ToArray(), "application/zip", zipName); } }
修正方案
1. 修正视图代码
- 给form标签添加
method="post",确保参数通过POST请求传递,而非GET - 移除多余的
FullFilePath隐藏域,将复选框的name统一设为FullfilePath(与控制器参数名一致),value设为对应文件的完整路径 - 添加全选/取消全选逻辑,提升用户体验
修正后的视图代码:
<form method="post"> <input type="hidden" name="FullFolderPath" value="@Model[0].FullFolderPath"> <table id="myTable" class="table CustomColorTable" border="1"> <thead> <tr> <th> <div class="icon icon-shape bg-indigo text-white rounded-circle shadow"> <i class="bi bi-folder2"></i> </div> <div> <input type="checkbox" id="selectAll"> Select All </div> </th> <th> <div class="icon icon-shape bg-indigo text-white rounded-circle shadow"> <i class="bi bi-folder2"></i> </div> <div>Folder Name</div> </th> <th> <div class="icon icon-shape bg-indigo text-white rounded-circle shadow"> <i class="bi bi-file-earmark-text"></i> </div> <div>File Name</div> </th> <th> <div class="icon icon-shape bg-indigo text-white rounded-circle shadow"> <i class="bi bi-calendar2-check"></i> </div> <div>Date Modified</div> </th> </tr> </thead> <tbody> @foreach (var item in Model) { <tr class="header"> <td> <div> <input type="checkbox" name="FullfilePath" value="@item.FullFilePath" id="@item.FullFilePath"> </div> </td> <td> @Html.DisplayFor(modelItem => item.FolderName) </td> <td> @Html.DisplayFor(modelItem => item.FileName) </td> <td> @Html.DisplayFor(modelItem => item.DateModified) </td> </tr> } </tbody> </table> <button id="btnSubmit" class="btnClick" asp-controller="Directory" asp-action="DownloadAll">Download Selected Items</button> </form> <script> // 全选逻辑 document.getElementById('selectAll').addEventListener('change', function() { const checkboxes = document.querySelectorAll('input[name="FullfilePath"]'); checkboxes.forEach(checkbox => checkbox.checked = this.checked); }); </script>
2. 修正控制器接收方法
- 将遍历文件夹所有文件的逻辑改为遍历传入的
FullfilePath数组,只压缩用户选中的文件 - 修复文件读取逻辑:原代码未读取实际文件内容,改为读取文件字节流
- 添加安全校验,确保选中的文件在目标文件夹范围内
修正后的控制器方法:
[HttpPost] public IActionResult DownLoadAll(string FullFolderPath, string[] FullfilePath) { if (FullFolderPath == null || FullfilePath == null || FullfilePath.Length == 0) { return View(); } var zipName = $"TestFiles-{DateTime.Now.ToString("yyyy_MM_dd-HH_mm_ss")}.zip"; using (MemoryStream ms = new MemoryStream()) { using (var zip = new ZipArchive(ms, ZipArchiveMode.Create, true)) { foreach (string filePath in FullfilePath) { // 安全校验:确保文件存在且在目标文件夹内 if (System.IO.File.Exists(filePath) && filePath.StartsWith(FullFolderPath, StringComparison.OrdinalIgnoreCase)) { var entry = zip.CreateEntry(Path.GetFileName(filePath)); using (var fileStream = System.IO.File.OpenRead(filePath)) using (var entryStream = entry.Open()) { fileStream.CopyTo(entryStream); } } }; } ms.Position = 0; return File(ms.ToArray(), "application/zip", zipName); } }
内容的提问来源于stack exchange,提问作者Hector Marcia
相关产品推荐
相关产品推荐

