2010-09-23 18 views
22

W języku C# ASP.net, czy ktoś mógłby mi pokazać, jak mogę zapisywać wpisy z tablicy/listy do pliku CSV na serwerze, a następnie otworzyć plik? Myślę, że druga część będzie coś w stylu - Response.Redirect ("http://myserver.com/file.csv"), ale nie jestem pewien, jak napisać plik na serwerze.Napisz do pliku CSV i wyeksportuj go?

Również, jeśli strona ta jest dostępna dla wielu użytkowników, czy lepiej jest za każdym razem wygenerować nowy plik CSV lub zastąpić ten sam plik? Czy wystąpią jakiekolwiek problemy z odczytem/zapisem/blokadą, jeśli obaj użytkownicy spróbują uzyskać dostęp do tego samego pliku CSV itp.?


Aktualizacja:

Prawdopodobnie jest to głupie pytanie i Szukałem w Google ale nie jestem w stanie znaleźć ostateczną odpowiedź - Jak napisać plik CSV do serwera WWW i wyeksportować go w C# ASP.net? Wiem, jak to wygenerować, ale chcę go zapisać na stronie www.mysite.com/my.csv, a następnie wyeksportować.

+0

Czy plik CSV będzie zawsze taka sama dla wszystkich użytkowników? – TheGeekYouNeed

Odpowiedz

47

Rom, robisz to źle. Nie chcesz zapisywać plików na dysku, aby usługi IIS mogły je obsłużyć. To dodaje implikacje bezpieczeństwa, a także zwiększa złożoność. Wszystko, co naprawdę musisz zrobić, to zapisać plik CSV bezpośrednio do strumienia odpowiedzi.

Oto scenariusz: użytkownik chce pobrać plik CSV. Użytkownik przesyła formularz ze szczegółami na temat żądanego CSV. Przygotowujesz csv, a następnie podajesz użytkownikowi adres URL strony aspx, której można użyć do skonstruowania pliku csv i zapisania go w strumieniu odpowiedzi. Użytkownik klika łącze. Strona aspx jest pusta; w kodzie strony po prostu napisz csv do strumienia odpowiedzi i zakończ go.

Można dodać następujące do (wierzę, że to jest poprawna) Load imprezy:

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

piśmie do odpowiedzi kod strumienia ganked from here.

+1

Należy używać metody Response.End() z ostrożnością. Więcej informacji: http://stackoverflow.com/questions/1087777/is-response-end-considered-harmful –

1

Jak zapisać do pliku (łatwe wyszukiwanie w Google) ... 1st Search Result

miarę tworzenia pliku za każdym razem użytkownik uzyskuje dostęp do strony ... każdy dostępu będzie działać na jego własnym imieniu. Twoja sprawa biznesowa będzie dyktować zachowanie.

Przypadek 1 - sam plik, ale nie zmienia się (ten typ przypadku może mieć wiele sposobów jest zdefiniowany)

  • Trzeba logikę, która utworzyła plik, gdy są potrzebne, a jedynie dostęp do pliku jeśli pokolenie nie są potrzebne.

Przypadek 2 - każdy użytkownik musi generować Ich własny plik

  • Można by zdecydować, w jaki sposób zidentyfikować każdego użytkownika, utwórz plik dla każdego użytkownika i dostępu do pliku są podobno zobaczyć ... można to łatwo połączyć z Przypadek 1. Następnie usuwa się plik po udostępnieniu treści, jeśli wymaga trwałości.

Przypadek 3 - sam plik, ale pokolenie wymagana dla każdego dostępu

  • przypadek użycia 2, spowoduje to pokolenie, za każdym razem, ale posprzątać po dostępu.
4

Oto wynik działania CSV, który napisałem, który pobiera DataTable i konwertuje go do pliku CSV. Możesz go zwrócić z widoku i poprosi użytkownika o pobranie pliku. Powinieneś być w stanie łatwo przekształcić to w formularz zgodny z Listą lub nawet umieścić swoją listę w 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

Wielkie dzięki. Pomógł mi w logice pliku csv i pobrać z przeglądarki. – Soader03

6

komentarz o odpowiedź będzie za, warto wymienić HttpContext.Current.Response.End(); z HttpContext.Current.ApplicationInstance.CompleteRequest(); Powodem jest to, że Response.End() rzuca System.Threading.ThreadAbortException. Przerywa wątek. Jeśli masz rejestrator wyjątków, będzie on zaśmiecony wyjątkami ThreadAbortExceptions, co w tym przypadku jest oczekiwanym zachowaniem.

Intuicyjnie, wysłanie pliku CSV do przeglądarki nie powinno powodować wyjątków.

Zobacz tutaj, aby uzyskać więcej Is Response.End() considered harmful?

21

Oto bardzo prosty darmowy open source klasy CsvExport dla C#. Na dole znajduje się przykład MVC ASP.NET.

https://github.com/jitbit/CsvExport

Dba o łamanie wierszy, przecinkami uciekających cytaty, zgodnością MS Excel ... Wystarczy dodać jeden krótki .cs plik do projektu i jesteś dobry, aby przejść.

(disclaimer: Jestem jednym z autorów)

+6

Osobiście chcę podziękować za udział i tę wspaniałą pracę. – LikePod

+0

dzięki. Wygląda na to że działa. – Reza