2010-09-23 8 views
22

In C# ASP.net, konnte mir jemand zeigen, wie ich Einträge aus einem Array/Liste in eine CSV-Datei auf dem Server schreiben und dann die Datei öffnen kann? Ich denke, der zweite Teil wäre etwas wie - Response.Redirect ("http://myserver.com/file.csv"), aber nicht sicher, wie man die Datei auf dem Server schreibt.In CSV-Datei schreiben und exportieren?

Auch wenn diese Seite von vielen Benutzern aufgerufen wird, ist es besser, jedes Mal eine neue CSV-Datei zu generieren oder die gleiche Datei zu überschreiben? Würde es Probleme beim Lesen/Schreiben/Sperren geben, wenn beide Benutzer versuchen, auf dieselbe CSV-Datei usw. zuzugreifen?


Update:

Dies ist wahrscheinlich eine dumme Frage ist, und ich habe auf Google gesucht, aber ich bin nicht in der Lage, eine endgültige Antwort zu finden - wie Sie ein CSV-Datei auf den Webserver schreiben und es exportiert in C# ASP.net? Ich weiß, wie man es erzeugt, aber ich möchte es auf www.mysite.com/my.csv speichern und dann exportieren.

+0

Ist die CSV-Datei wird immer das gleiche für alle Benutzer sein? – TheGeekYouNeed

Antwort

47

Rom, bist du es falsch zu machen. Sie möchten keine Dateien auf den Datenträger schreiben, damit IIS sie bereitstellen kann. Das erhöht die Sicherheit und erhöht die Komplexität. Sie müssen lediglich die CSV-Datei direkt im Antwort-Stream speichern.

Hier ist das Szenario: Benutzer möchte csv herunterladen. Der Benutzer sendet ein Formular mit Details zum gewünschten csv. Sie bereiten den csv vor und stellen dem Benutzer dann eine URL zu einer aspx-Seite zur Verfügung, mit der die csv-Datei erstellt und in den Antwortstream geschrieben werden kann. Der Benutzer klickt auf den Link. Die aspx-Seite ist leer. in der Seite codebehind schreibst du einfach den csv in den Antwortstream und beendest ihn.

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()); 

Schreiben in den Antwortstream Code ganked from here:

Sie können die folgenden auf die (ich glaube, das ist richtig) Load Ereignis hinzuzufügen.

+1

Verwenden Sie Response.End() mit Vorsicht. Weitere Informationen: http://stackoverflow.com/questions/1087777/is-response-end-consided-harmful –

1

Wie in eine Datei (einfache Suche in Google) ... 1st Search Result

Soweit Erstellung der Datei jedes Mal, wenn ein Benutzer auf die Seite ... jeden Zugriff wirkt auf seinen eigenen Namen zu schreiben. Ihr Geschäftsfall bestimmt das Verhalten.

Fall 1 - gleiche Datei aber nicht ändert (diese Art von Fall mehr Möglichkeiten, wobei definiert hat)

  • Sie Logik, die die Datei erstellt haben würde, wenn nötig und nur Zugriff auf die Datei, wenn Generation nicht benötigt.

Fall 2 - jeder braucht Benutzer ihre eigenen Datei

    erzeugen
  • Sie würden entscheiden, wie Sie die einzelnen Benutzer identifizieren, um eine Datei für jeden Benutzer erstellen und Zugriff auf die Datei, die sie sehen sollen ... Dies kann leicht mit Fall 1 verschmelzen. Dann löschen Sie die Datei nach dem Servieren des Inhalts oder nicht, wenn es Persistenz erfordert.

Fall 3 - gleiche Datei aber Generation für jeden dies,

  • Use Case 2

    Zugang erforderlich verursachen jedes Mal eine Generation aber einmal zugegriffen aufzuräumen.
4

Hier ist ein CSV-Aktionsergebnis, das ich schrieb, das eine DataTable nimmt und sie in CSV konvertiert. Sie können dies aus Ihrer Sicht zurückgeben, und der Benutzer wird aufgefordert, die Datei herunterzuladen. Sie sollten in der Lage sein, dies leicht in ein Listen-kompatibles Formular zu konvertieren oder einfach Ihre Liste in eine DataTable zu schreiben.

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

Vielen Dank. Hat mir geholfen mit der Logik der CSV-Datei und dem Download aus dem Browser. – Soader03

6

Ein Kommentar über die Antwort von Will, möchten Sie vielleicht HttpContext.Current.Response.End(); mit HttpContext.Current.ApplicationInstance.CompleteRequest(); Der Grund zu ersetzen ist, dass Response.End() eine System.Threading.ThreadAbortException wirft. Es bricht einen Thread ab. Wenn Sie einen Ausnahme-Logger haben, wird er mit ThreadAbortExceptions übersät sein, was in diesem Fall das erwartete Verhalten ist.

Intuitiv sollte das Senden einer CSV-Datei an den Browser keine Ausnahme auslösen.

Sehen Sie hier für mehr Is Response.End() considered harmful?

21

Hier ist eine sehr einfache kostenlose Open-Source CsvExport Klasse für C#. Unten finden Sie ein ASP.NET MVC-Beispiel.

https://github.com/jitbit/CsvExport

Es kümmert sich um Zeilenumbrüche, Kommas, Flucht zitiert, MS Excel compatibilty ... Fügen Sie einfach eine kurze .cs Datei zu Ihrem Projekt und Sie sind gut zu gehen.

(Disclaimer: Ich bin einer der Mitwirkenden)

+6

Ich möchte Ihnen persönlich für Ihren Anteil und diese großartige Arbeit danken. – LikePod

+0

danke. es scheint zu funktionieren. – Reza

Verwandte Themen