【问题标题】:Write to CSV file and export it?写入 CSV 文件并导出?
【发布时间】:2011-04-16 05:26:05
【问题描述】:

在 C# ASP.net 中,有人可以告诉我如何将 Array/List 中的条目写入服务器上的 CSV 文件,然后打开该文件吗?我认为第二部分类似于 - Response.Redirect("http://myserver.com/file.csv"),但不确定如何在服务器上写入文件。

另外,如果这个页面被很多用户访问,是每次生成一个新的 CSV 文件还是覆盖同一个文件更好?如果两个用户都尝试访问同一个 CSV 文件等,是否会出现任何读/写/锁定问题?


更新:

这可能是一个愚蠢的问题,我在 Google 上进行了搜索,但找不到明确的答案 - 如何将 CSV 文件写入网络服务器并将其导出到 C# ASP.net 中?我知道如何生成它,但我想将其保存到 www.mysite.com/my.csv 然后导出。

【问题讨论】:

  • 所有用户的 CSV 文件是否始终相同?

标签: c# asp.net csv export


【解决方案1】:

这是一个非常简单的 C# 的免费开源 CsvExport 类。底部有一个 ASP.NET MVC 示例。

https://github.com/jitbit/CsvExport

它会处理换行符、逗号、转义引号、MS Excel 兼容性...只需在您的项目中添加一个简短的 .cs 文件即可。

(免责声明:我是贡献者之一)

【讨论】:

  • 我个人要感谢您的分享和出色的工作。
【解决方案2】:

Rom,你做错了。您不想将文件写入磁盘以便 IIS 可以提供它们。这增加了安全隐患并增加了复杂性。您真正需要做的就是将 CSV 直接保存到响应流中。

场景如下:用户希望下载 csv。用户提交一份包含他们想要的 csv 详细信息的表单。您准备好 csv,然后向用户提供一个指向 aspx 页面的 URL,该页面可用于构建 csv 文件并将其写入响应流。用户点击链接。 aspx 页面是空白的;在页面代码隐藏中,您只需将 csv 写入响应流并结束它。

您可以将以下内容添加到(我相信这是正确的)Load 事件中:

string attachment = "attachment; filename=MyCsvLol.csv";
HttpContext.Current.Response.Clear();
HttpContext.Current.Response.ClearHeaders();
HttpContext.Current.Response.ClearContent();
HttpContext.Current.Response.AddHeader("content-disposition", attachment);
HttpContext.Current.Response.ContentType = "text/csv";
HttpContext.Current.Response.AddHeader("Pragma", "public");

var sb = new StringBuilder();
foreach(var line in DataToExportToCSV)
  sb.AppendLine(TransformDataLineIntoCsv(line));

HttpContext.Current.Response.Write(sb.ToString());

写入响应流代码ganked from here

【讨论】:

【解决方案3】:

关于威尔回答的评论,你可能想用HttpContext.Current.ApplicationInstance.CompleteRequest(); 替换HttpContext.Current.Response.End(); 原因是Response.End() 抛出了System.Threading.ThreadAbortException。它中止一个线程。如果您有一个异常记录器,它将被 ThreadAbortExceptions 乱扔,在这种情况下这是预期的行为。

直观地说,向浏览器发送 CSV 文件不应引发异常。

查看更多Is Response.End() considered harmful?

【讨论】:

    【解决方案4】:

    这是我编写的 CSV 操作结果,它采用 DataTable 并将其转换为 CSV。您可以从您的视图中返回它,它会提示用户下载文件。您应该能够轻松地将其转换为与列表兼容的形式,甚至只是将您的列表放入数据表中。

    using System;
    using System.Text;
    using System.Collections.Generic;
    using System.Linq;
    using System.Web;
    using System.Web.Mvc;
    using System.Data;
    
    namespace Detectent.Analyze.ActionResults
    {
        public class CSVResult : ActionResult
        {
            /// <summary>
            /// Converts the columns and rows from a data table into an Microsoft Excel compatible CSV file.
            /// </summary>
            /// <param name="dataTable"></param>
            /// <param name="fileName">The full file name including the extension.</param>
            public CSVResult(DataTable dataTable, string fileName)
            {
                Table = dataTable;
                FileName = fileName;
            }
    
            public string FileName { get; protected set; }
            public DataTable Table { get; protected set; }
    
    
    
    
            public override void ExecuteResult(ControllerContext context)
            {
                StringBuilder csv = new StringBuilder(10 * Table.Rows.Count * Table.Columns.Count);
    
                for (int c = 0; c < Table.Columns.Count; c++)
                {
                    if (c > 0)
                        csv.Append(",");
                    DataColumn dc = Table.Columns[c];
                    string columnTitleCleaned = CleanCSVString(dc.ColumnName);
                    csv.Append(columnTitleCleaned);
                }
                csv.Append(Environment.NewLine);
                foreach (DataRow dr in Table.Rows)
                {
                    StringBuilder csvRow = new StringBuilder();
                    for(int c = 0; c < Table.Columns.Count; c++)
                    {
                        if(c != 0)
                            csvRow.Append(",");
    
                        object columnValue = dr[c];
                        if (columnValue == null)
                            csvRow.Append("");
                        else
                        {
                            string columnStringValue = columnValue.ToString();
    
    
                            string cleanedColumnValue = CleanCSVString(columnStringValue);
    
                            if (columnValue.GetType() == typeof(string) && !columnStringValue.Contains(","))
                            {
                                cleanedColumnValue = "=" + cleanedColumnValue; // Prevents a number stored in a string from being shown as 8888E+24 in Excel. Example use is the AccountNum field in CI that looks like a number but is really a string.
                            }
                            csvRow.Append(cleanedColumnValue);
                        }
                    }
                    csv.AppendLine(csvRow.ToString());
                }
    
                HttpResponseBase response = context.HttpContext.Response;
                response.ContentType = "text/csv";
                response.AppendHeader("Content-Disposition", "attachment;filename=" + this.FileName);
                response.Write(csv.ToString());
            }
    
            protected string CleanCSVString(string input)
            {
                string output = "\"" + input.Replace("\"", "\"\"").Replace("\r\n", " ").Replace("\r", " ").Replace("\n", "") + "\"";
                return output;
            }
        }
    }
    

    【讨论】:

    • 非常感谢。帮助我了解 csv 文件的逻辑并从浏览器下载。
    【解决方案5】:

    【讨论】:

      【解决方案6】:

      如何写入文件(在 Google 中轻松搜索)...1st Search Result

      就每次用户访问页面时文件的创建而言......每次访问都将代表它自己。您的业​​务案例将决定行为。

      案例 1 - 相同的文件但没有改变(这种类型的案例可以有多种定义方式)

      • 您将拥有在需要时创建文件并仅在不需要生成时才访问文件的逻辑。

      案例 2 - 每个用户都需要生成自己的文件

      • 您将决定如何识别每个用户,为每个用户创建一个文件并访问他们应该看到的文件...这可以很容易地与案例 1 合并。然后在提供内容后删除文件,如果这需要坚持。

      案例 3 - 相同的文件,但每次访问都需要生成

      • 用例 2,这将导致每次生成,但一旦访问就会清理。

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 2018-12-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2019-11-17
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多