在 C# 中导入 CSV 文件 | ASP.NET Core教程 | IronXL
在ASP.NET Core中使用 C# 导入 CSV 文件意味着需要读取文件流、解析分隔行,并将每条记录映射到类型化对象——所有这些操作都必须在对数据进行任何有用的操作之前完成。 IronXL通过一个 API 处理每个步骤,该 API 对 CSV、XLSX 和 TSV 文件同样适用,因此您可以将时间用于应用程序逻辑,而不是处理字符串分割等极端情况。
立即开始免费试用,即可跟随教程并在您自己的环境中测试这些代码示例。
如何在.NET项目中安装IronXL ?
在编写任何解析代码之前,请将IronXL添加到您的项目中。 在 Visual Studio 中打开包管理器控制台,或者在项目目录中打开终端,然后运行以下命令之一:
Install-Package IronXL.Excel
该软件包面向.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}");
}
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 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.");
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
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}");
}
}
}
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.");
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();
}
}
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>();
builder.Services.AddScoped<CsvImportService>();
然后更新控制器构造器以接受服务,并调用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.");
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调用同时处理这两者。 这种一致性意味着您可以随着应用程序需求的增长,逐步扩展导入端点的功能集。
常见问题解答
如何在ASP.NET Core应用程序中导入 CSV 文件?
您可以使用IronXL在ASP.NET Core应用程序中导入 CSV 文件,方法是处理文件上传、解析 CSV 数据并将其映射到模型类对象。IronXL 提供了一个 API 来高效地完成这些任务。
在 C# 中使用IronXL进行 CSV 导入有哪些好处?
IronXL提供了一个 API,简化了 CSV 文件的导入过程。它允许您轻松解析数据、将其映射到模型并将记录转换为 JSON,使其成为数据驱动型应用程序的理想选择。
IronXL能否将CSV数据解析为模型类对象?
是的, IronXL可以将 CSV 数据解析为模型类对象,从而让您在.NET应用程序中高效地处理结构化数据。
在导入 CSV 文件时, IronXL如何帮助进行数据库集成?
IronXL通过解析 CSV 数据并将其映射到模型对象来帮助数据库集成,这些模型对象可以轻松地插入或更新到数据库中。
是否可以使用IronXL将 CSV 记录转换为 JSON 格式返回?
是的,使用IronXL,您可以将 CSV 记录转换为 JSON 格式,这对于创建 Web API 或与前端应用程序集成非常有用。
除了 CSV 格式外, IronXL还能处理哪些文件格式?
除了 CSV 格式外, IronXL还可以处理各种 Excel 文件格式,如 XLSX、XLS 等,为不同的电子表格需求提供了多功能性。
IronXL是否支持导入大型CSV文件?
IronXL旨在高效处理大型 CSV 文件导入,确保数据驱动型应用程序的性能和可靠性。




