如何不生成临时文件直接将上传CSV文件流写入IList<string>
解决方案
完全可以实现,无需将上传文件保存为临时文件,直接通过流读取即可完成需求。
实现思路
- 直接调用
IFormFile.OpenReadStream()获取上传文件的可读流,没有磁盘IO开销 - 用
StreamReader包裹流逐行读取内容,存入List<string>即可,List天然实现了IList<string>接口
原生实现代码(无第三方依赖)
using System.IO; using System.Text; using System.Collections.Generic; // 可根据需要调整返回值,或者把IList<string>作为入参传入 public IList<string> FileToIList(IFormFile importFile) { IList<string> csvLines = new List<string>(); if (importFile == null || importFile.Length == 0) { return csvLines; } // 如果CSV为GBK/GB2312编码,先取消下方注释注册编码提供程序 // Encoding.RegisterProvider(CodePagesEncodingProvider.Instance); // 然后将下方的Encoding.UTF8替换为Encoding.GetEncoding("GBK") using var streamReader = new StreamReader(importFile.OpenReadStream(), Encoding.UTF8); string currentLine; while ((currentLine = streamReader.ReadLine()) != null) { // 可在此处添加过滤逻辑,例如跳过空行、跳过CSV表头行 if (!string.IsNullOrWhiteSpace(currentLine)) { csvLines.Add(currentLine); } } return csvLines; }
进阶实现(适配含特殊格式的CSV)
如果CSV存在引号包裹的单元格内换行场景,直接逐行读取会出现拆分错误,建议使用专用CSV处理库解析,避免格式解析异常:
// 需先安装NuGet包:CsvHelper using CsvHelper; using CsvHelper.Configuration; using System.Globalization; using System.IO; using System.Text; using System.Collections.Generic; public IList<string> FileToIList(IFormFile importFile) { IList<string> csvLines = new List<string>(); if (importFile == null || importFile.Length == 0) { return csvLines; } var csvConfig = new CsvConfiguration(CultureInfo.InvariantCulture) { Delimiter = ",", // 根据CSV实际分隔符调整,常见为逗号/制表符 Encoding = Encoding.UTF8, AllowComments = false }; using var streamReader = new StreamReader(importFile.OpenReadStream(), csvConfig.Encoding); using var csvReader = new CsvReader(streamReader, csvConfig); while (csvReader.Read()) { // RawRecord为当前完整行的原始内容,自动处理了嵌套换行的场景 csvLines.Add(csvReader.Context.RawRecord.TrimEnd('\r', '\n')); } return csvLines; }
注意事项
- 所有流对象都用
using块包裹,会自动释放资源,无需手动关闭流 - 若上传的CSV文件体积过大,全量读取到内存可能引发内存溢出,建议按行分批处理业务逻辑,不要全量存入
IList<string>
内容的提问来源于stack exchange,提问作者Christian01
相关产品推荐
相关产品推荐

