【问题标题】:Exporting data to CSV from Controller将数据从 Controller 导出到 CSV
【发布时间】:2014-02-20 04:55:24
【问题描述】:

我在 ASP.NET MVC 项目中使用 CsvHelper 库将数据导出到 CSV,我发现导出的数据要么被截断,要么在较小列表的情况下,没有数据被写入完全没有,我收到一个空白的 CSV 文件。

我的基本控制器有一个这样的方法(由从此类继承的控制器调用以导出实体列表):

protected FileContentResult GetExportFileContentResult(IList data, string filename)
    {
        using (var memoryStream = new MemoryStream())
        {
            using (var streamWriter = new StreamWriter(memoryStream))
            {
                using (var csvWriter = new CsvWriter(streamWriter))
                {
                    csvWriter.WriteRecords(data);
                    return File(memoryStream.ToArray(), "text/csv", filename);
                }
            }
        }
    }

随着列表 1k+ 项的导出,最后几项似乎被切断了。当项目列表小于 ~100 时,返回的 CSV 文件为空白且不包含任何数据。

我尝试直接写入输出流而不是 MemoryStream,并收到了相同的结果。

还尝试删除 using 语句以防流被过早释放,但也没有导致任何更改。

使用此库正确创建 CSV 文件的正确方法是什么(即包含所有行,并且无论列表大小如何都能正常工作)?

编辑

决定使用 CsvHelper 报废并改用另一个名为 CsvTools 的库。这工作没有任何问题。我的代码如下供参考。

protected FileContentResult GetExportFileContentResult(IList data, string filename)
{
    using (var memoryStream = new MemoryStream())
    {
            using (var streamWriter = new StreamWriter(memoryStream))
            {
                var dt = DataTable.New.FromEnumerable(data);
                dt.SaveToStream(streamWriter);
                return File(memoryStream.ToArray(), "text/csv", filename);
        }
    }
}

顺便说一句,尝试了 Simon 在下面直接使用内存流而不是调用 ToArray 的建议,但收到关于流被关闭的错误,并且还没有开始调试。

【问题讨论】:

  • 顺便说一句:考虑使用实际的MemoryStream 对象从File().. 返回,这样它就变成了FileStreamResult。这以块的形式流式传输到浏览器,并且不分配大对象。
  • 嘿,这篇文章很有用,但是没有 MemoryStream 我们怎么能做到呢?

标签: c# asp.net-mvc csvhelper csvtools


【解决方案1】:

原因是您没有将写入器中的数据刷新到流中。当写入器已满时,写入器会定期刷新,但您需要确保在最后执行此操作。

选项 1:

using (var memoryStream = new MemoryStream())
using (var streamWriter = new StreamWriter(memoryStream))
using (var csvWriter = new CsvWriter(streamWriter))
{
    csvWriter.WriteRecords(data);
    streamWriter.Flush();
    memoryStream.Position = 0;
    return File(memoryStream, "text/csv", filename);
}

选项 2:

using (var memoryStream = new MemoryStream())
{
    using (var streamWriter = new StreamWriter(memoryStream))
    using (var csvWriter = new CsvWriter(streamWriter))
    {
        csvWriter.WriteRecords(data);
    } // The stream gets flushed here.
    memoryStream.Position = 0;
    return File(memoryStream, "text/csv", filename);
}

【讨论】:

  • 我正在为 CsvHelper 使用 CsvFactory 类,所以有点不同,但是 textWriter.Flush() 为我解决了问题!谢谢!
  • 挑剔,但在选项 2 中,您可以使用 memoryStream.ToArray() 作为 File() 的第一个参数,而不是将 Position 设置回 0。
猜你喜欢
  • 2014-07-26
  • 2018-02-12
  • 1970-01-01
  • 1970-01-01
  • 2021-04-04
  • 2020-09-11
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多