写入CSV文件并导出?

时间:2010-09-23 11:34:36

标签: c# asp.net csv export

在C#ASP.net中,有人可以告诉我如何将数组/列表中的条目写入服务器上的CSV文件,然后打开文件吗?我认为第二部分可能是 - Response.Redirect(“http://myserver.com/file.csv”),但不确定如何在服务器上写文件。

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


更新

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

6 个答案:

答案 0 :(得分:53)

罗姆,你做错了。您不希望将文件写入磁盘,以便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

答案 1 :(得分:24)

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

https://github.com/jitbit/CsvExport

它关注换行符,逗号,转义引号,MS Excel兼容性......只需在项目中添加一个简短的.cs文件,就可以了。

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

答案 2 :(得分:6)

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

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

请点击此处查看更多Is Response.End() considered harmful?

答案 3 :(得分:5)

以下是我编写的CSV操作结果,它采用DataTable并将其转换为CSV。您可以从视图中返回此内容,它将提示用户下载该文件。您应该可以轻松地将其转换为List兼容表单,甚至只需将列表放入DataTable。

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;
        }
    }
}

答案 4 :(得分:1)

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

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

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

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

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

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

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

  • 使用案例2,每次都会产生一代,但一旦访问就会清理。

答案 5 :(得分:0)

相关问题