Asp.net-Core

為什麼 CsvHelper 不從 MemoryStream 讀取?

  • March 16, 2022

我正在嘗試將上傳的 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();
   }

這裡最常見的錯誤是忘記MemoryStream二進制;它以字節為單位。你需要一些涉及角色的東西,這並不總是 1:1 的改編。MemoryStream好消息是您通過將a包裝起來避免了該錯誤StreamReader

using (var reader = new StreamReader(stream))

StreamReaderimplements TextReader,它適用於字元而不是字節。耶!壞消息是 StreamReader 是在這一行之後創建的:

filePayload.CopyTo(stream);

問題是那條線離開了指向數據末尾的流。當您嘗試從中讀取時,流中沒有任何內容。

要解決此問題,您需要做的就是回到起點。所以這:

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))

引用自:https://stackoverflow.com/questions/49434920