2010-09-23 32 views
22

En C# ASP.net, ¿alguien podría mostrarme cómo puedo escribir entradas de una matriz/lista en un archivo CSV en el servidor y luego abrir el archivo? Creo que la segunda parte sería algo así como: Response.Redirect ("http://myserver.com/file.csv"), pero no estoy seguro de cómo escribir el archivo en el servidor.¿Escribir en el archivo CSV y exportarlo?

Además, si muchos usuarios acceden a esta página, ¿es mejor generar un nuevo archivo CSV cada vez o sobrescribir el mismo archivo? ¿Habrá problemas de lectura/escritura/bloqueo si ambos usuarios intentan acceder al mismo archivo CSV, etc.?


Actualización:

Esta es probablemente una pregunta tonta y he buscado en Google pero no soy capaz de encontrar una respuesta definitiva - ¿cómo se escribe un archivo CSV al servidor web y exportarlo en C# ASP.net? Sé cómo generarlo, pero me gustaría guardarlo en www.mysite.com/my.csv y luego exportarlo.

+0

es el archivo CSV va a ser siempre el mismo para todos los usuarios? – TheGeekYouNeed

Respuesta

47

Rom, lo estás haciendo mal. No desea escribir archivos en el disco para que IIS pueda servirlos. Eso agrega implicaciones de seguridad y aumenta la complejidad. Todo lo que necesitas hacer es guardar el archivo CSV directamente en la secuencia de respuesta.

Aquí está el escenario: El usuario desea descargar csv. El usuario envía un formulario con detalles sobre el csv que desea. Usted prepara el csv, luego proporciona al usuario una URL a una página aspx que puede usarse para construir el archivo csv y escribirlo en la secuencia de respuesta. El usuario hace clic en el enlace. La página aspx está en blanco; en el código de la página detrás de usted simplemente escriba la csv en la secuencia de respuesta y finalícela.

Usted puede añadir lo siguiente a la (creo que esto es correcto) 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()); 

escrito al código de secuencia de respuesta ganked from here.

+1

Use Response.End() con precaución. Más información: http://stackoverflow.com/questions/1087777/is-response-end-considered-harmful –

1

cómo escribir en un archivo (búsqueda fácil en Google) ... 1st Search Result

En cuanto a la creación del archivo cada vez que un usuario accede a la página ... cada acceso actuará en su propio nombre. Su caso comercial dictará el comportamiento.

Caso 1 - mismo archivo, pero no cambiar (este tipo de casos puede tener múltiples formas de ser definido)

  • Usted tendría lógica que creó el archivo cuando sea necesario y sólo acceder al archivo si la generación es innecesario.

Caso 2 - cada usuario necesita generar su propio archivo

  • Se podría decidir cómo identificar a cada usuario, crea un archivo para cada usuario y acceder al archivo que se supone que ver ... esto puede fusionarse fácilmente con el Caso 1. Luego, borra el archivo después de publicar el contenido o no, si requiere persistencia.

Caso 3 - mismo archivo pero la generación requerida para cada acceso

  • Caso de uso 2, esto hará que una generación cada vez, pero una vez obtenida a limpiar.
4

Aquí hay un resultado de acción CSV que escribí que toma una DataTable y la convierte en CSV. Puede devolver esto desde su vista y le pedirá al usuario que descargue el archivo. Debería poder convertir esto fácilmente en un formulario compatible con la Lista o incluso simplemente poner su lista en una 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

Muchas gracias. Me ayudó con la lógica del archivo csv y la descarga desde el navegador. – Soader03

6

Un comentario sobre la respuesta de Will, es posible que desee reemplazar HttpContext.Current.Response.End(); con HttpContext.Current.ApplicationInstance.CompleteRequest(); La razón es que Response.End() tiros un System.Threading.ThreadAbortException. Anula un hilo. Si tiene un registrador de excepciones, estará lleno de ThreadAbortExceptions, que en este caso es el comportamiento esperado.

Intuitivamente, el envío de un archivo CSV al navegador no debe generar una excepción.

Consulte aquí para obtener más Is Response.End() considered harmful?

21

Aquí hay una muy simple clase gratis CsvExport de código abierto para C#. Hay un ejemplo de ASP.NET MVC en la parte inferior.

https://github.com/jitbit/CsvExport

Se toma cuidado sobre saltos de línea, comas, comillas, que escapan compatibilty MS Excel ... Sólo tiene que añadir un archivo corto .cs a su proyecto y ya está bueno para ir.

(exención de responsabilidad: Soy uno de los contribuyentes)

+6

personalmente quiero agradecerle por su participación y este gran trabajo. – LikePod

+0

gracias. Parece estar funcionando. – Reza

Cuestiones relacionadas