
在 C# 中导入 CSV 文件 | ASP.NET Core教程 | IronXL
在ASP.NET Core中使用 C# 导入 CSV 文件意味着需要读取文件流、解析分隔行,并将每条记录映射到类型化对象——所有这些操作都必须在对数据进行任何有用的操作之前完成。 IronXL通过一个 API 处理每个步骤,该 API 对 CSV、XLSX 和 TSV 文件同样适用,因此您可以将时间用于应用程序逻辑,而不是处理字符串分割等极端情况。
立即开始免费试用,即可跟随教程并在您自己的环境中测试这些代码示例。
如何在.NET项目中安装IronXL ?
在编写任何解析代码之前,请将IronXL添加到您的项目中。 在 Visual Studio 中打开包管理器控制台,或者在项目目录中打开终端,然后运行以下命令之一:
该软件包面向.NET 10、 .NET 6+、. .NET Framework 4.6.2+ 和.NET Standard 2.0,因此适用于任何现代项目类型。 服务器上无需安装微软Office。 在包恢复后,在调用库的任何文件顶部添加using IronXL;。
有关详细的设置选项,包括全局工具安装和 CI/CD 管道配置,请访问IronXL安装指南。
如何在ASP.NET Core中导入 CSV 文件?
在ASP.NET Core中导入 CSV 文件需要从服务器读取文件流,解析每一行,并将值映射到模型类。 虽然一些开发者寻求手动的StreamReader实现或第三方包,IronXL提供了一种单一的方法,可以处理CSV文件和Excel格式,无需额外配置。
以下代码展示了如何使用IronXL的WorkBook.LoadCSV方法加载CSV文件:
using IronXL;
// Load the CSV file directly using the full file path
var csv = WorkBook.LoadCSV("products.csv");
WorkSheet worksheet = csv.DefaultWorkSheet;
// Access CSV data by iterating through rows
foreach (var row in worksheet.Rows)
{
string productName = row.Columns[1].StringValue;
decimal price = row.Columns[2].DecimalValue;
Console.WriteLine($"Product: {productName}, Price: {price}");
}Imports IronXL
' Load the CSV file directly using the full file path
Dim csv = WorkBook.LoadCSV("products.csv")
Dim worksheet As WorkSheet = csv.DefaultWorkSheet
' Access CSV data by iterating through rows
For Each row In worksheet.Rows
Dim productName As String = row.Columns(1).StringValue
Dim price As Decimal = row.Columns(2).DecimalValue
Console.WriteLine($"Product: {productName}, Price: {price}")
Next了解 WorkBook.LoadCSV 方法
WorkBook.LoadCSV方法读取CSV文件并创建一个工作表,其中每行成为一行,每个分隔值成为一个单元格。 IronXL会自动检测分隔符(逗号、分号或制表符),并处理值中包含逗号的带引号的字段。 对于标准 CSV 文件,无需手动配置分隔符。
像decimal.Parse进行手动解析。 当单元格为空或包含无法识别的值时,这些访问器会返回类型的默认值,而不是抛出异常,从而防止在批量导入操作期间出现未处理的错误。
这种方法消除了自定义实现中容易出错的手动字符串解析,特别是对于转义引号、Windows 风格的换行符和多行单元格值等特殊情况。 有关支持的格式和分隔符选项的更多详细信息,请参阅IronXL CSV 文档。

如何为 CSV 数据创建模型类?
将 CSV 数据映射到强类型对象需要一个反映文件结构的模型类。 您可以将原始字符串数据转换为特定类型,例如整数、小数和日期时间值。 对于产品库存数据,创建一个类,其属性与每个 CSV 列相匹配:
public class Product
{
public int Id { get; set; }
public string Name { get; set; } = string.Empty;
public decimal Price { get; set; }
public int Quantity { get; set; }
}Public Class Product
Public Property Id As Integer
Public Property Name As String = String.Empty
Public Property Price As Decimal
Public Property Quantity As Integer
End Class将 CSV 行解析为类型化集合
定义好模型类后,就可以将 CSV 记录解析为类型化集合。 以下示例使用循环索引跳过标题行,将每个后续行映射到Product对象:
using IronXL;
WorkBook workbook = WorkBook.LoadCSV("inventory.csv");
WorkSheet ws = workbook.DefaultWorkSheet;
var records = new List<Product>();
// Skip header row (index 0), iterate through data rows
for (int i = 1; i < ws.Rows.Count(); i++)
{
var row = ws.Rows[i];
var product = new Product
{
Id = row.Columns[0].IntValue,
Name = row.Columns[1].StringValue,
Price = row.Columns[2].DecimalValue,
Quantity = row.Columns[3].IntValue
};
records.Add(product);
}
Console.WriteLine($"Loaded {records.Count} products.");Imports IronXL
Dim workbook As WorkBook = WorkBook.LoadCSV("inventory.csv")
Dim ws As WorkSheet = workbook.DefaultWorkSheet
Dim records As New List(Of Product)()
' Skip header row (index 0), iterate through data rows
For i As Integer = 1 To ws.Rows.Count() - 1
Dim row = ws.Rows(i)
Dim product As New Product With {
.Id = row.Columns(0).IntValue,
.Name = row.Columns(1).StringValue,
.Price = row.Columns(2).DecimalValue,
.Quantity = row.Columns(3).IntValue
}
records.Add(product)
Next
Console.WriteLine($"Loaded {records.Count} products.")Product对象。 IronXL 的单元格值访问器会自动处理类型转换,包括可选字段的空值处理。
处理可选字段和可为空字段
实际的 CSV 文件经常包含空单元格或可选列。 IronXL 的值访问器在单元格为空时返回默认值,而不是抛出异常。 对于可为空的类型,您可以使用条件检查:
// Reading an optional DateTime field
DateTime? lastUpdated = string.IsNullOrEmpty(row.Columns[4].StringValue)
? null
: row.Columns[4].DateTimeValue;' Reading an optional DateTime field
Dim lastUpdated As DateTime? = If(String.IsNullOrEmpty(row.Columns(4).StringValue), Nothing, row.Columns(4).DateTimeValue)这种模式可以保护你的导入代码,而无需将每个单元格访问都包装在 try-catch 块中。 有关处理复杂数据类型和大型文件的指导,请访问IronXL WorkSheet 文档。
如何在 Web API 中处理 CSV 文件上传?
构建一个接受来自浏览器的CSV文件上传的API端点,需要结合ASP.NET Core的IFormFile和IronXL的解析能力。 以下代码演示了一个完整的控制器实现,该控制器解析上传的文件并返回 JSON 响应:
using IronXL;
using Microsoft.AspNetCore.Mvc;
[Route("api/[controller]")]
[ApiController]
public class CsvController : ControllerBase
{
[HttpPost("upload")]
public async Task<IActionResult> UploadCsv(IFormFile file)
{
if (file == null || file.Length == 0)
return BadRequest("Please upload a valid CSV file.");
try
{
using var stream = new MemoryStream();
await file.CopyToAsync(stream);
stream.Position = 0;
WorkBook workbook = WorkBook.Load(stream, "csv");
WorkSheet ws = workbook.DefaultWorkSheet;
var records = new List<Product>();
// Skip header row, iterate through data rows
for (int i = 1; i < ws.Rows.Count(); i++)
{
var row = ws.Rows[i];
records.Add(new Product
{
Id = row.Columns[0].IntValue,
Name = row.Columns[1].StringValue,
Price = row.Columns[2].DecimalValue,
Quantity = row.Columns[3].IntValue
});
}
return Ok(new
{
message = "Import successful",
count = records.Count,
data = records
});
}
catch (Exception ex)
{
return BadRequest($"Error processing file: {ex.Message}");
}
}
}Imports IronXL
Imports Microsoft.AspNetCore.Mvc
Imports System.IO
Imports System.Threading.Tasks
<Route("api/[controller]")>
<ApiController>
Public Class CsvController
Inherits ControllerBase
<HttpPost("upload")>
Public Async Function UploadCsv(file As IFormFile) As Task(Of IActionResult)
If file Is Nothing OrElse file.Length = 0 Then
Return BadRequest("Please upload a valid CSV file.")
End If
Try
Using stream As New MemoryStream()
Await file.CopyToAsync(stream)
stream.Position = 0
Dim workbook As WorkBook = WorkBook.Load(stream, "csv")
Dim ws As WorkSheet = workbook.DefaultWorkSheet
Dim records As New List(Of Product)()
' Skip header row, iterate through data rows
For i As Integer = 1 To ws.Rows.Count() - 1
Dim row = ws.Rows(i)
records.Add(New Product With {
.Id = row.Columns(0).IntValue,
.Name = row.Columns(1).StringValue,
.Price = row.Columns(2).DecimalValue,
.Quantity = row.Columns(3).IntValue
})
Next
Return Ok(New With {
.message = "Import successful",
.count = records.Count,
.data = records
})
End Using
Catch ex As Exception
Return BadRequest($"Error processing file: {ex.Message}")
End Try
End Function
End Class配置端点和多部分表单
要让[HttpPost("upload")]动作接受文件上传,项目必须支持多部分表单数据。 在app.MapControllers()。 此端点可以在/api/csv/upload访问。
从浏览器表单进行测试时,将表单的multipart/form-data并使用文件输入元素。 对于像Postman这样的API客户端,在请求体中选择"form-data",添加一个名为file的键,并附上CSV文件。控制器返回一个JSON对象,其中包含记录数和可供客户端JavaScript立即使用的解析数据数组。

解析前验证文件类型
在将数据流传递给IronXL之前,请验证文件扩展名,拒绝非 CSV 格式的上传文件:
var extension = Path.GetExtension(file.FileName).ToLowerInvariant();
if (extension != ".csv" && extension != ".txt")
return BadRequest("Only CSV files are accepted.");Dim extension As String = Path.GetExtension(file.FileName).ToLowerInvariant()
If extension <> ".csv" AndAlso extension <> ".txt" Then
Return BadRequest("Only CSV files are accepted.")
End If此检查可防止格式错误的二进制数据到达解析器,并向 API 使用者提供清晰的错误消息。 可以使用file.ContentType进行更严格的强制执行,扩展此验证以检查MIME类型。
如何将CSV数据保存到数据库?
将 CSV 文件解析为类型化对象后,通常会将记录持久化到数据库中。 以下示例通过使用Entity Framework Core的AddRangeAsync进行批量插入来扩展服务层模式:
using IronXL;
public class CsvImportService
{
private readonly AppDbContext _context;
public CsvImportService(AppDbContext context)
{
_context = context;
}
public async Task<int> ImportProductsAsync(Stream csvStream)
{
WorkBook workbook = WorkBook.LoadCSV(csvStream);
WorkSheet ws = workbook.DefaultWorkSheet;
var products = new List<Product>();
foreach (var row in ws.Rows.Skip(1))
{
products.Add(new Product
{
Id = row.Columns[0].IntValue,
Name = row.Columns[1].StringValue,
Price = row.Columns[2].DecimalValue,
Quantity = row.Columns[3].IntValue
});
}
await _context.Products.AddRangeAsync(products);
return await _context.SaveChangesAsync();
}
}Imports IronXL
Public Class CsvImportService
Private ReadOnly _context As AppDbContext
Public Sub New(context As AppDbContext)
_context = context
End Sub
Public Async Function ImportProductsAsync(csvStream As Stream) As Task(Of Integer)
Dim workbook As WorkBook = WorkBook.LoadCSV(csvStream)
Dim ws As WorkSheet = workbook.DefaultWorkSheet
Dim products As New List(Of Product)()
For Each row In ws.Rows.Skip(1)
products.Add(New Product With {
.Id = row.Columns(0).IntValue,
.Name = row.Columns(1).StringValue,
.Price = row.Columns(2).DecimalValue,
.Quantity = row.Columns(3).IntValue
})
Next
Await _context.Products.AddRangeAsync(products)
Return Await _context.SaveChangesAsync()
End Function
End Class将服务集成到依赖注入中
在CsvImportService,这样控制器就可以通过构造器注入请求它:
builder.Services.AddScoped<CsvImportService>();net然后更新控制器构造器以接受服务,并调用ImportProductsAsync,而不是内联构建列表。这种分离保持了控制器动作的精简,并将数据访问逻辑移到可测试的服务类中。 Entity Framework Core将INSERT语句,这对于包含数千行的CSV文件表现良好。
对于非常大的导入(数万行),考虑使用EF Core's Bulk Extensions 或者原始SQL BULK INSERT语句以减少与数据库的往返。
如何使用IronXL将数据导出回 CSV 文件?
IronXL不仅限于读取 CSV 文件,它还可以写入 CSV 文件。 SaveAsCsv方法将任何工作表导出为一个CSV文件,这对于生成报告或发送数据到下游系统很有用:
using IronXL;
WorkBook workbook = WorkBook.Create(ExcelFileFormat.XLS);
WorkSheet ws = workbook.DefaultWorkSheet;
// Write headers
ws["A1"].Value = "Id";
ws["B1"].Value = "Name";
ws["C1"].Value = "Price";
// Write data rows
ws["A2"].Value = 1;
ws["B2"].Value = "Widget A";
ws["C2"].Value = 9.99;
ws["A3"].Value = 2;
ws["B3"].Value = "Widget B";
ws["C3"].Value = 14.49;
// Save as CSV
workbook.SaveAsCsv("export.csv");
Console.WriteLine("CSV export complete.");Imports IronXL
Dim workbook As WorkBook = WorkBook.Create(ExcelFileFormat.XLS)
Dim ws As WorkSheet = workbook.DefaultWorkSheet
' Write headers
ws("A1").Value = "Id"
ws("B1").Value = "Name"
ws("C1").Value = "Price"
' Write data rows
ws("A2").Value = 1
ws("B2").Value = "Widget A"
ws("C2").Value = 9.99
ws("A3").Value = 2
ws("B3").Value = "Widget B"
ws("C3").Value = 14.49
' Save as CSV
workbook.SaveAsCsv("export.csv")
Console.WriteLine("CSV export complete.")导出的文件默认使用逗号分隔符。 对于在欧洲地区常见的分号分隔文件,使用明确的分隔符参数调用SaveAsCsv("export.csv", ";")。 您还可以保存到File(stream, "text/csv", "export.csv")从API端点返回结果作为文件下载。
有关导出选项的完整参考,请访问IronXL保存和导出文档。
为什么IronXL比手动解析 CSV 文件更好?
手动解析 CSV 文件看起来很简单,直到你遇到一些特殊情况:例如,包含用引号括起来的逗号的值、嵌入在单元格中的换行符、转义的引号以及 UTF-8 文件开头的字节顺序标记。 在自定义StreamReader循环中正确处理所有这些需要大量测试和持续维护。
IronXL在内部解决了所有这些问题。 对比两种方法,可以明显看出它们的优势:
| 能力 | IronXL | 手动 StreamReader |
|---|---|---|
| 自动分隔符检测 | 是 | 否——必须手动配置 |
| 引用字段处理 | 内置 | 需要自定义逻辑 |
| 类型转换(整数、十进制、日期时间) | 内置配件 | 需要调用 Parse/TryParse 函数 |
| 多行单元格值 | 自动处理 | 难以正确实施 |
| 物料清单处理 | 自动翻译 | 需要 StreamReader 配置 |
| Excel格式支持(XLSX、XLS) | 相同的 API | 需要单独的库 |
| 导出为 CSV | SaveAsCsv 方法 | 需要单独的写入逻辑 |
跨格式一致性
IronXL的一个实际优势是同样的WorkBook.Load和工作表迭代模式适用于XLSX、XLS、ODS和CSV文件。 如果您的应用程序需要接受用户提供的多种电子表格格式,您可以在不更改解析逻辑的情况下切换格式。 将文件流传递给WorkBook.Load,IronXL会根据文件签名自动检测格式。
这种跨格式 API 意味着您只需编写和测试一条代码路径,而无需为 CSV 和 Excel 分别维护单独的实现。 有关支持的格式的完整列表,请参阅IronXL支持的文件格式页面。
大文件的性能考虑因素
对于小于 100 MB 的 CSV 文件, IronXL无需任何调整即可良好运行。 对于较大的文件,请考虑以下策略:
- 从路径加载文件而不是将其复制到
MemoryStream以减少内存分配。 - 将数据插入数据库时,分批处理行,而不是在第一次插入之前收集所有记录。
- 使用
Product对象。
IronXL性能指南涵盖了针对高容量导入场景的额外优化,包括并行处理和流模式。
下一步计划是什么?
现在,您已经拥有了ASP.NET Core中 CSV 导入每个阶段的工作模式:安装库、从磁盘或上传的流加载文件、将行映射到类型化模型对象、使用 Entity Framework Core 将记录持久化到数据库,以及在需要时将数据导出回 CSV。
在此基础上,您可以探索以下资源:
- IronXL NuGet包-- NuGet上的包详细信息和版本历史记录 IronXL教程概述——涵盖筛选、公式计算和图表生成的指导性教程 IronXL API 参考——完整的类和方法文档
- IronXL GitHub示例-- GitHub上可下载的示例项目 IronXL许可选项——针对开发、测试和生产环境的许可级别
- Microsoft CSV 解析文档-- IronXL所基于的.NET IO 模型背景
- ASP.NET Core文件上传文档-- 关于 IFormFile 和 multipart 上传配置的官方指南 IronXL读取和导入 Excel 教程——涵盖读取 XLSX 和 CSV 文件。
- IronXL创建和写入教程 -- 包括写入数据和以多种格式保存的内容
- IronXL数据排序和筛选——加载后对导入数据进行操作
在您的项目中使用IronXL,并行支持XLSX上传与CSV,无需额外的代码更改——同样的WorkBook.Load调用同时处理这两者。 这种一致性意味着您可以随着应用程序需求的增长,逐步扩展导入端点的功能集。

Curtis Chau 拥有卡尔顿大学的计算机科学学士学位,专注于前端开发,精通 Node.js、TypeScript、JavaScript 和 React。他热衷于打造直观且美观的用户界面,喜欢使用现代框架并创建结构良好、视觉吸引力强的手册。
相关文章



