ASP.NET C# MVC实现DataTable选中行逐行导出为独立文本文件
解决方案:ASP.NET MVC 导出DataTable选中行为单独文本文件
一、无执行结果的常见排查点
- 未正确传递选中行标识:视图未将选中行的关键数据(如主键)提交到控制器
- 文件夹路径问题:目标文件夹不存在,或应用程序池身份无写入权限
- 逻辑错误:遍历DataTable时未定位到选中行,或文本内容拼接出错
- 请求方式不匹配:控制器方法标记
[HttpPost]但视图用GET提交,反之亦然
二、修正后的完整实现
1. 控制器代码
using System; using System.Data; using System.IO; using System.Linq; using System.Web.Mvc; public class HomeController : Controller { // 替换为你的IBM AS400数据查询逻辑 private DataTable GetAS400Data() { DataTable dt = new DataTable(); // 根据实际AS400表结构定义列 dt.Columns.Add("ID", typeof(int)); dt.Columns.Add("CustomerName", typeof(string)); dt.Columns.Add("Phone", typeof(string)); // 示例数据,实际替换为AS400查询结果 dt.Rows.Add(1, "ABC公司", "010-12345678"); dt.Rows.Add(2, "DEF商行", "021-87654321"); dt.Rows.Add(3, "XYZ工厂", "020-11223344"); return dt; } public ActionResult Index() { DataTable dt = GetAS400Data(); return View(dt); } [HttpPost] public ActionResult ConvertToTextfile(int[] selectedIds) { // 定义导出目录,优先用App_Data避免权限问题 string exportDir = Server.MapPath("~/App_Data/ExportedTexts"); if (!Directory.Exists(exportDir)) { Directory.CreateDirectory(exportDir); } DataTable fullData = GetAS400Data(); // 遍历选中行生成文件 foreach (int id in selectedIds) { DataRow targetRow = fullData.Select($"ID = {id}").FirstOrDefault(); if (targetRow != null) { // 按需求拼接文本内容,可调整字段顺序和格式 string textContent = $"客户ID: {targetRow["ID"]}\r\n" + "客户名称: " + targetRow["CustomerName"] + "\r\n" + "联系电话: " + targetRow["Phone"]; // 生成唯一文件名,防止覆盖 string fileName = $"Customer_{id}_{DateTime.Now:yyyyMMddHHmmssfff}.txt"; string fullPath = Path.Combine(exportDir, fileName); // 写入文件,AS400数据若为EBCDIC编码需转成UTF-8/GBK File.WriteAllText(fullPath, textContent, System.Text.Encoding.UTF8); } } TempData["ExportResult"] = $"成功导出 {selectedIds.Length} 条记录,路径:{exportDir}"; return RedirectToAction("Index"); } }
2. 视图代码(Index.cshtml)
@model System.Data.DataTable @{ ViewBag.Title = "客户数据列表"; } <h2>客户数据列表</h2> @if (TempData["ExportResult"] != null) { <div class="alert alert-success">@TempData["ExportResult"]</div> } @using (Html.BeginForm("ConvertToTextfile", "Home", FormMethod.Post)) { <button type="submit" class="btn btn-primary mb-3">导出选中记录为独立文本</button> <table class="table table-striped"> <thead> <tr> <th><input type="checkbox" id="selectAll" /></th> <th>客户ID</th> <th>客户名称</th> <th>联系电话</th> </tr> </thead> <tbody> @foreach (DataRow row in Model.Rows) { <tr> <td><input type="checkbox" name="selectedIds" value="@row["ID"]" /></td> <td>@row["ID"]</td> <td>@row["CustomerName"]</td> <td>@row["Phone"]</td> </tr> } </tbody> </table> } <script> // 全选/取消全选逻辑 document.getElementById('selectAll').onchange = function() { const checkboxes = document.querySelectorAll('input[name="selectedIds"]'); checkboxes.forEach(cb => cb.checked = this.checked); }; </script>
三、关键注意事项
- 权限配置:确保应用程序池身份对导出目录有写入权限,
App_Data目录默认具备该权限 - 编码适配:若AS400返回EBCDIC编码数据,需先通过编码转换工具转成UTF-8/GBK,避免乱码
- 异常处理:可在控制器方法中添加
try-catch块,捕获文件写入、数据查询异常并返回错误提示 - 性能优化:若数据量极大,建议直接在AS400查询时筛选选中行,避免加载全量数据到内存
内容的提问来源于stack exchange,提问作者Imene ZARAI
相关产品推荐
相关产品推荐

