2010-09-23 18 views
22

In C# ASP.net, qualcuno potrebbe mostrarmi come posso scrivere le voci da un array/elenco a un file CSV sul server e quindi aprire il file? Penso che la seconda parte sarebbe qualcosa di simile - Response.Redirect ("http://myserver.com/file.csv"), tuttavia non sono sicuro su come scrivere il file sul server.Scrivere nel file CSV ed esportarlo?

Anche se questa pagina è accessibile da molti utenti, è meglio generare un nuovo file CSV ogni volta o sovrascrivere lo stesso file? Ci sarebbero problemi di lettura/scrittura/blocco se entrambi gli utenti provano ad accedere allo stesso file CSV, ecc.?


Aggiornamento:

Questa è probabilmente una domanda stupida e ho cercato su Google ma non sono in grado di trovare una risposta definitiva - come si fa a scrivere un file CSV per il server web ed esportarli in C# ASP.net? So come generarlo ma vorrei salvarlo su www.mysite.com/my.csv e quindi esportarlo.

+0

è il file CSV sarà sempre lo stesso per tutti gli utenti? – TheGeekYouNeed

risposta

47

Rom, si sta facendo male. Non si desidera scrivere file sul disco in modo che IIS possa servirli. Ciò aggiunge implicazioni per la sicurezza e aumenta la complessità. Tutto ciò che devi davvero fare è salvare il CSV direttamente nel flusso di risposta.

Ecco lo scenario: l'utente desidera scaricare CSV. L'utente invia un modulo con i dettagli relativi alla CSV che desidera. Preparare il CSV, quindi fornire all'utente un URL a una pagina ASPX che può essere utilizzato per costruire il file CSV e scriverlo nel flusso di risposta. L'utente fa clic sul collegamento. La pagina di aspx è vuota; nella pagina codebehind semplicemente scrivi il csv nel flusso di risposta e terminalo.

È possibile aggiungere il seguente al (credo che questo sia corretto) Load evento:

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

iscritto al codice di flusso di risposta ganked from here.

+1

Utilizzare Response.End() con cautela. Maggiori informazioni: http://stackoverflow.com/questions/1087777/is-response-end-considered-harmful –

1

Come scrivere in un file (ricerca facile in Google) ... 1st Search Result

Per quanto riguarda la creazione del file ogni volta che un utente accede alla pagina ... ogni accesso agirà per conto di essa la propria. Il tuo caso aziendale determinerà il comportamento.

Caso 1 - stesso file, ma non modifica (questo tipo di casi può avere più modi di essere definito)

  • Avreste logica che ha creato il file quando necessario e accedere solo il file se generazione è non necessario.

Caso 2 - ogni utente ha bisogno per generare il proprio file

  • Si potrebbe decidere come identificare ogni utente, crea un file per ogni utente e accedere al file che si suppone a vedere ... questo può facilmente fondersi con il caso 1. Quindi si elimina il file dopo aver servito il contenuto o meno se richiede persistenza.

Caso 3 - stesso file, ma la generazione necessaria per ogni accesso

  • Use Case 2, questo causerà una generazione di volta in volta, ma ripulire una volta si accede.
4

Ecco un risultato di azione CSV che ho scritto che prende un DataTable e lo converte in CSV. È possibile restituirlo dalla propria vista e richiederà all'utente di scaricare il file. Dovresti essere in grado di convertirlo facilmente in un modulo compatibile con List o anche solo di inserire la tua lista in un 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

Grazie mille. Mi ha aiutato con la logica del file CSV e scaricato dal browser. – Soader03

6

Un commento sulla risposta di Will, si potrebbe desiderare di sostituire HttpContext.Current.Response.End(); con HttpContext.Current.ApplicationInstance.CompleteRequest(); Il motivo è che Response.End() getta un System.Threading.ThreadAbortException. Interrompe un thread. Se si dispone di un logger di eccezioni, sarà pieno di ThreadAbortExceptions, che in questo caso è il comportamento previsto.

In modo intuitivo, l'invio di un file CSV al browser non dovrebbe generare un'eccezione.

Vedi qui per maggiori Is Response.End() considered harmful?

21

Ecco un semplice libero classe CsvExport open-source per C#. C'è un esempio MVC ASP.NET in fondo.

https://github.com/jitbit/CsvExport

Si occupa circa interruzioni di linea, virgole, virgolette fuga, MS Excel compatibilità ... Basta aggiungere un breve file di .cs al progetto e si sta bene ad andare.

(disclaimer: io sono uno dei collaboratori)

+6

personalmente voglio ringraziarvi per la vostra condivisione e questo ottimo lavoro. – LikePod

+0

grazie. sembra che funzioni. – Reza

Problemi correlati