2010-09-23 174 views
22

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

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


更新:

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

+0

CSV文件对所有用户来说总是相同吗? – TheGeekYouNeed 2010-09-23 11:43:24

回答

47

ROM检查出csvreader /写库,你这样做是错误的。您不想将文件写入磁盘,以便IIS可以为其提供服务。这增加了安全隐患并增加了复杂性。您真正需要做的就是直接将CSV保存到响应流中。

这里是场景:用户希望下载csv。用户提交表单并提供他们想要的csv的详细信息。您准备csv,然后为用户提供一个可以用于构建csv文件并将其写入响应流的aspx页面的URL。用户点击链接。 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

谨慎使用Response.End()。更多信息:http://stackoverflow.com/questions/1087777/is-response-end-considered-harmful – 2015-05-18 16:14:40

1

如何在用户每次访问的页面......每个接入将采取行动以自己的名义它的时间写入文件(在谷歌搜索方便)... 1st Search Result

至于创建文件。你的商业案例将决定行为。

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

  • 你会在需要的时候创建该文件的逻辑,如果一代只能访问文件不需要。

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

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

案例3 - 每个接入

  • 使用案例2需要相同的文件,但一代,这将导致一代每次但清理一次访问。
4

这是我写的一个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; 
     } 
    } 
} 
+0

非常感谢。帮助我使用csv文件的逻辑并从浏览器下载。 – Soader03 2014-06-04 14:48:56

6

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

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

在这里看到更多Is Response.End() considered harmful?

21

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

https://github.com/jitbit/CsvExport

大约需要换行符,逗号,引号逃逸,MS Excel中了兼容性护理...只是一个短期.cs文件添加到您的项目,你是好去。

(声明:我是其中一位参与者)

+6

我个人想感谢您的分享和这项伟大的工作。 – LikePod 2016-03-08 22:26:20

+0

谢谢。它似乎在工作。 – Reza 2017-03-28 14:11:40

相关问题