【问题标题】:How to Export CSV file from ASP.NET core如何从 ASP.NET 核心导出 CSV 文件
【发布时间】:2019-03-15 10:37:06
【问题描述】:

我正在尝试将代码从 ASP.net 迁移到 ASP.net 核心。

ASP.net 中的代码如下所示,

var progresses = db.Progresses.Where(p => p.UserId == id).Include(p => p.User.UserMetaData).Include(p => p.Quiz).Include(p => p.User.Groups).OrderByDescending(p => p.UpdatedAt).ToList();

List<ReportCSVModel> reportCSVModels = new List<ReportCSVModel>();
const string downloadName = "Reports.csv";
var csv = new CsvWriter(Response.Output);

csv.Configuration.RegisterClassMap<ReportCSVMap>();

Response.ClearContent();

Response.ContentType = "application/octet-stream";

Response.AddHeader("Content-Disposition",
   "attachment; filename=" + downloadName);

csv.WriteHeader<ReportCSVModel>();
foreach (var progress in progresses)
{
    var reportCSVModel = new ReportCSVModel();
    reportCSVModel.Quiz = progress.Quiz.Title;
    reportCSVModel.Score = (progress.CorrectAnswersCount * progress.PointsPerQuestion).ToString();
    reportCSVModel.Status = progress.Status;
    reportCSVModel.CompletedDate = progress.UpdatedAt.ToString();
    reportCSVModel.Location = progress.User.UserMetaData != null ? progress.User.UserMetaData.Location : "";
    reportCSVModel.Group = progress.User.Groups.FirstOrDefault() != null ? progress.User.Groups.FirstOrDefault().Name : "";

    csv.WriteRecord<ReportCSVModel>(reportCSVModel);
}
Response.Flush();
Response.End();
return null;

但在 ASP.NET 核心中使用它时,我将其转换为,

var progresses = _elearnContext.Progress.Where(p => p.UserId == id).Include(p => p.User.UserMetaData).Include(p => p.Quiz).Include(p => p.User.Groups).OrderByDescending(p => p.UpdatedAt).ToList();

// List<ReportCSVModel> reportCSVModels = new List<ReportCSVModel>();
List<ReportCSVModel> reportCSVModels = new List<ReportCSVModel>();
const string downloadName = "Reports.csv";

System.IO.TextWriter writeFile = new StreamWriter(Response.Body.ToString());
CsvWriter csv = new CsvWriter(writeFile);
csv.Configuration.RegisterClassMap<GroupReportCSVMap>();
Response.Clear();
Response.ContentType = "application/octet-stream";
Response.Headers.Add("Content-Disposition", "attachment; filename=" + downloadName);


csv.WriteHeader<ReportCSVModel>();
foreach (var progress in progresses)
{
    var reportCSVModel = new ReportCSVModel();
    reportCSVModel.Quiz = progress.Quiz.Title;
    reportCSVModel.Score = (progress.CorrectAnswersCount * progress.PointsPerQuestion).ToString();
    reportCSVModel.Status = progress.Status;
    reportCSVModel.CompletedDate = progress.UpdatedAt.ToString();
    reportCSVModel.Location = progress.User.UserMetaData != null ? progress.User.UserMetaData.Location : "";
    reportCSVModel.Group = progress.User.Groups.FirstOrDefault() != null ? progress.User.Groups.FirstOrDefault().Name : "";

    csv.WriteRecord<ReportCSVModel>(reportCSVModel);
}

Response.Clear();
return null;

在 ASP.net 中,Response.Output 可用,但在核心中不可用。所以我试着像Response.Body一样使用它

谁能告诉我,我哪里做错了?

【问题讨论】:

    标签: c# asp.net-core-mvc export-to-csv csv-write-stream


    【解决方案1】:

    考虑改变方法以更符合当前建议的语法。

    构造 CSV 并返回一个 FileResult,这样代码就不必直接操作 Response 对象。

    [HttpGet]
    public IActionResult MyExportAction() {
        var progresses = _elearnContext.Progress.Where(p => p.UserId == id)
            .Include(p => p.User.UserMetaData)
            .Include(p => p.Quiz)
            .Include(p => p.User.Groups)
            .OrderByDescending(p => p.UpdatedAt)
            .ToList()
            .Select(progress => 
                new ReportCSVModel() {
                    Quiz = progress.Quiz.Title,
                    Score = (progress.CorrectAnswersCount * progress.PointsPerQuestion).ToString(),
                    Status = progress.Status,
                    CompletedDate = progress.UpdatedAt.ToString(),
                    Location = progress.User.UserMetaData != null ? progress.User.UserMetaData.Location : "",
                    Group = progress.User.Groups.FirstOrDefault() != null ? progress.User.Groups.FirstOrDefault().Name : ""
                }
            );
    
        List<ReportCSVModel> reportCSVModels = progresses.ToList();
    
        var stream = new MemoryStream();
        using(var writeFile = new StreamWriter(stream, leaveOpen: true)) {
            var csv = new CsvWriter(writeFile, true);
            csv.Configuration.RegisterClassMap<GroupReportCSVMap>();            
            csv.WriteRecords(reportCSVModels);
        }
        stream.Position = 0; //reset stream
        return File(stream, "application/octet-stream", "Reports.csv");
    }
    

    【讨论】:

    • 我发现如果在csv.WriteRecords(reportCSVModels)之后不添加writeFile.Flush(),CSV文件最终会是空的。
    • @jdoer1997 不错。将 writer 包装在 using 块中也会在处理之前刷新它。
    • 这种方法是否意味着整个 csv 在创建时正在帮助内存?
    【解决方案2】:
    using CsvHelper;
    using CsvHelper.Configuration;
    
    namespace projectX.Controllers {
      [Route("MyController")]
      public class MyController : Controller {
        [Route("export")]
        [HttpGet]
        public ActionResult export() {
          var cc = new CsvConfiguration(new System.Globalization.CultureInfo("en-US"));
          using (var ms = new MemoryStream()) {
            using (var sw = new StreamWriter(stream: ms, encoding: new UTF8Encoding(true))) {
              using (var cw = new CsvWriter(sw, cc)) {
                cw.WriteRecords(YourGenericList);
              }// The stream gets flushed here.
              return File(ms.ToArray(), "text/csv", $"export_{DateTime.UtcNow.Ticks}.csv");
            }
          }
        }
      }
    }
    

    感谢Exporting data to CSV from Controller

    【讨论】:

      【解决方案3】:

      //安装包CsvHelper

      //控制器编码

          public async Task<IActionResult> indiainfected(ExcelDownloadIndiaInfected exceldownloadindiainfected)
          { 
              var excel =await downloadReportsRepository.ExcelSheetAddIndiaInfected(exceldownloadindiainfected);
              var cc = new CsvConfiguration(new System.Globalization.CultureInfo("en-US"));
              var stream = new MemoryStream();
              using (var sw = new StreamWriter(stream: stream, encoding: newUTF8Encoding(true)))
              {
                  using (var cw = new CsvWriter(sw, cc))
                  {
                      cw.WriteRecords(excel);
                  }
                  
              }
              string csvName = $"India_Infected-{DateTime.UtcNow.Ticks}.csv";
              return File(stream.ToArray(), "text/csv", csvName);
          }
      

      【讨论】:

        猜你喜欢
        • 2012-05-21
        • 2021-12-08
        • 2021-04-06
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2019-01-11
        • 1970-01-01
        相关资源
        最近更新 更多