为什么CsvHelper无法从MemoryStream读取?

Ana*_*and 8 csvhelper asp.net-core

我正在尝试将上传的csv文件转换为对象,以便可以保存在db中。在控制器中,我正在使用CsvHeler

但是看起来这只有在我首先保存文件并从中读取时才有效。CsvHelper无法直接从内存流中处理文件内容。在第一个GetRecords下面的代码中返回空

    [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();
    }
Run Code Online (Sandbox Code Playgroud)

Joe*_*orn 8

MemoryStream是二进制的。它以字节为单位。您需要一些处理字符的东西。好消息是您尝试过;你有这个:

using (var reader = new StreamReader(stream))
Run Code Online (Sandbox Code Playgroud)

StreamReader实现TextReader,它使用字符而不是字节。好极了!坏消息是在此行之后立即创建了StreamReader:

filePayload.CopyTo(stream);
Run Code Online (Sandbox Code Playgroud)

问题在于该行使流指向数据的末尾。当您尝试从中读取内容时,流中什么也没剩下。

解决此问题所需要做的只是重新寻找。所以这:

using (var stream = new MemoryStream())
{
    filePayload.CopyTo(stream);
    using (var reader = new StreamReader(stream))
Run Code Online (Sandbox Code Playgroud)

变成这个:

using (var stream = new MemoryStream())
{
    filePayload.CopyTo(stream);
    stream.Seek(0, SeekOrigin.Begin)

    using (var reader = new StreamReader(stream))
Run Code Online (Sandbox Code Playgroud)