I am trying to convert an uploaded csv file to an object, so i can save in db. In the controller I am using CsvHeler
But looks like this only works if I first save the file and read from it. CsvHelper is not able to process the file contents directly from memory stream. In the code below the first 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();
}
The most common error here is forgetting MemoryStream
is binary; it deals in bytes. You need something that deals in characters, which isn't always a 1:1 adaption. The good news is you avoided that error by wrapping the MemoryStream
in a StreamReader
:
using (var reader = new StreamReader(stream))
StreamReader
implements TextReader
, which works with characters rather than bytes. Yay! The bad news is the StreamReader is created right after this line:
filePayload.CopyTo(stream);
The problem was that line left the stream pointed at the end of the data. When you try to read from it, there's nothing left in the stream.
All you should need to do to fix this is seek back to the beginning. So this:
using (var stream = new MemoryStream())
{
filePayload.CopyTo(stream);
using (var reader = new StreamReader(stream))
Becomes this:
using (var stream = new MemoryStream())
{
filePayload.CopyTo(stream);
stream.Seek(0, SeekOrigin.Begin);
using (var reader = new StreamReader(stream))
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With