为什么 CsvHelper 不从 MemoryStream 读取?
Why CsvHelper not reading from MemoryStream?
我正在尝试将上传的 csv 文件转换为对象,以便我可以保存在数据库中。
在控制器中,我使用的是 CsvHeler
但看起来这只有在我先保存文件并从中读取时才有效。 CsvHelper 无法直接从内存流中处理文件内容。在下面的代码中,第一个 GetRecords returns empty
[HttpPost]
[Route(ApiRoutes.EodVariationMarginPlugs)]
public async Task<IActionResult> UploadPlugAsync(IFormFile filePayload)
{
if (filePayload.Length > 0)
{
using (var stream = new MemoryStream())
{
filePayload.CopyTo(stream);
using (var reader = new StreamReader(stream))
using (var csv = new CsvReader(reader))
{
csv.Configuration.RegisterClassMap<EodVariationMarginPlugMap>();
csv.Configuration.MissingFieldFound = null;
var records = csv.GetRecords<EodVariationMarginPlug>().ToList(); // record count is 0
foreach (var p in records)
{
p.CreatedAt = DateTimeOffset.Now;
p.CreatedBy = HttpContext.User.Identity.Name;
}
await _repository.InsertPlugsAsync(records);
}
}
var fileName = ContentDispositionHeaderValue
.Parse(filePayload.ContentDisposition)
.FileName.ToString().Trim('"');
var path = Path.Combine(Path.GetTempPath(), fileName);
using (var fileStream = new FileStream(path, FileMode.Create))
{
await filePayload.CopyToAsync(fileStream);
}
var textReader = System.IO.File.OpenText(path);
using (var csv = new CsvReader(textReader))
{
csv.Configuration.RegisterClassMap<EodVariationMarginPlugMap>();
csv.Configuration.MissingFieldFound = null;
var records = csv.GetRecords<EodVariationMarginPlug>().ToList();
foreach (var p in records)
{
p.CreatedAt = DateTimeOffset.Now;
p.CreatedBy = HttpContext.User.Identity.Name;
}
await _repository.InsertPlugsAsync(records);
}
}
return Ok();
}
这里最常见的错误是忘记了 MemoryStream
是二进制的;它以字节为单位。您需要处理角色的东西,这并不总是 1:1 改编。好消息是您通过将 MemoryStream
包装在 StreamReader
:
中避免了该错误
using (var reader = new StreamReader(stream))
StreamReader
实现了 TextReader
,它使用字符而不是字节。耶!坏消息是 StreamReader 是在这一行之后创建的:
filePayload.CopyTo(stream);
问题是该行使流指向数据的 end。当您尝试从中读取时,流中没有任何内容。
要解决此问题,您需要做的就是回到开头。所以这个:
using (var stream = new MemoryStream())
{
filePayload.CopyTo(stream);
using (var reader = new StreamReader(stream))
变成这样:
using (var stream = new MemoryStream())
{
filePayload.CopyTo(stream);
stream.Seek(0, SeekOrigin.Begin);
using (var reader = new StreamReader(stream))
我正在尝试将上传的 csv 文件转换为对象,以便我可以保存在数据库中。 在控制器中,我使用的是 CsvHeler
但看起来这只有在我先保存文件并从中读取时才有效。 CsvHelper 无法直接从内存流中处理文件内容。在下面的代码中,第一个 GetRecords returns empty
[HttpPost]
[Route(ApiRoutes.EodVariationMarginPlugs)]
public async Task<IActionResult> UploadPlugAsync(IFormFile filePayload)
{
if (filePayload.Length > 0)
{
using (var stream = new MemoryStream())
{
filePayload.CopyTo(stream);
using (var reader = new StreamReader(stream))
using (var csv = new CsvReader(reader))
{
csv.Configuration.RegisterClassMap<EodVariationMarginPlugMap>();
csv.Configuration.MissingFieldFound = null;
var records = csv.GetRecords<EodVariationMarginPlug>().ToList(); // record count is 0
foreach (var p in records)
{
p.CreatedAt = DateTimeOffset.Now;
p.CreatedBy = HttpContext.User.Identity.Name;
}
await _repository.InsertPlugsAsync(records);
}
}
var fileName = ContentDispositionHeaderValue
.Parse(filePayload.ContentDisposition)
.FileName.ToString().Trim('"');
var path = Path.Combine(Path.GetTempPath(), fileName);
using (var fileStream = new FileStream(path, FileMode.Create))
{
await filePayload.CopyToAsync(fileStream);
}
var textReader = System.IO.File.OpenText(path);
using (var csv = new CsvReader(textReader))
{
csv.Configuration.RegisterClassMap<EodVariationMarginPlugMap>();
csv.Configuration.MissingFieldFound = null;
var records = csv.GetRecords<EodVariationMarginPlug>().ToList();
foreach (var p in records)
{
p.CreatedAt = DateTimeOffset.Now;
p.CreatedBy = HttpContext.User.Identity.Name;
}
await _repository.InsertPlugsAsync(records);
}
}
return Ok();
}
这里最常见的错误是忘记了 MemoryStream
是二进制的;它以字节为单位。您需要处理角色的东西,这并不总是 1:1 改编。好消息是您通过将 MemoryStream
包装在 StreamReader
:
using (var reader = new StreamReader(stream))
StreamReader
实现了 TextReader
,它使用字符而不是字节。耶!坏消息是 StreamReader 是在这一行之后创建的:
filePayload.CopyTo(stream);
问题是该行使流指向数据的 end。当您尝试从中读取时,流中没有任何内容。
要解决此问题,您需要做的就是回到开头。所以这个:
using (var stream = new MemoryStream())
{
filePayload.CopyTo(stream);
using (var reader = new StreamReader(stream))
变成这样:
using (var stream = new MemoryStream())
{
filePayload.CopyTo(stream);
stream.Seek(0, SeekOrigin.Begin);
using (var reader = new StreamReader(stream))