Exportar a CSV usando MVC, C # y jQuery

85

Estoy intentando exportar una lista a un archivo CSV. Lo tengo todo funcionando hasta el punto en que quiero escribir en el archivo del flujo de respuesta. Esto no hace nada.

Aquí está mi código:

Llame al método de la página.

$('#btn_export').click(function () {
         $.post('NewsLetter/Export');
});

El código en el controlador es el siguiente:

[HttpPost]
        public void Export()
        {
            try
            {
                var filter = Session[FilterSessionKey] != null ? Session[FilterSessionKey] as SubscriberFilter : new SubscriberFilter();

                var predicate = _subscriberService.BuildPredicate(filter);
                var compiledPredicate = predicate.Compile();
                var filterRecords = _subscriberService.GetSubscribersInGroup().Where(x => !x.IsDeleted).AsEnumerable().Where(compiledPredicate).GroupBy(s => s.Subscriber.EmailAddress).OrderBy(x => x.Key);

                ExportAsCSV(filterRecords);
            }
            catch (Exception exception)
            {
                Logger.WriteLog(LogLevel.Error, exception);
            }
        }

        private void ExportAsCSV(IEnumerable<IGrouping<String, SubscriberInGroup>> filterRecords)
        {
            var sw = new StringWriter();
            //write the header
            sw.WriteLine(String.Format("{0},{1},{2},{3}", CMSMessages.EmailAddress, CMSMessages.Gender, CMSMessages.FirstName, CMSMessages.LastName));

            //write every subscriber to the file
            var resourceManager = new ResourceManager(typeof(CMSMessages));
            foreach (var record in filterRecords.Select(x => x.First().Subscriber))
            {
                sw.WriteLine(String.Format("{0},{1},{2},{3}", record.EmailAddress, record.Gender.HasValue ? resourceManager.GetString(record.Gender.ToString()) : "", record.FirstName, record.LastName));
            }

            Response.Clear();
            Response.AddHeader("Content-Disposition", "attachment; filename=adressenbestand.csv");
            Response.ContentType = "text/csv";
            Response.Write(sw);
            Response.End();
        }

Pero después de que Response.Write(sw)no pasa nada. ¿Es posible guardar un archivo de esta manera?

Saludos

Editar
Los encabezados de respuesta que veo cuando hago clic en el botón son:

HTTP/1.1 200 OK
Cache-Control: private
Content-Type: text/csv; charset=utf-8
Server: Microsoft-IIS/7.5
X-AspNetMvc-Version: 2.0
Content-Disposition: attachment; filename=adressenbestand.csv
X-Powered-By: ASP.NET
Date: Wed, 12 Jan 2011 13:05:42 GMT
Content-Length: 113

Lo que me parece bien ...

Editar
Me deshice de la parte de jQuery y la reemplacé por un hipervínculo y esto funciona bien para mí ahora:

<a class="export" href="NewsLetter/Export">exporteren</a>
Gerard
fuente
1
Quizás esta pregunta sobre SO ayude: stackoverflow.com/questions/4522590/…
Rob
¿Podría documentar su respuesta como una respuesta real en lugar de editar la pregunta?
Caltor

Respuestas:

250

yan.kun estaba en el camino correcto, pero esto es mucho más fácil.

    public FileContentResult DownloadCSV()
    {
        string csv = "Charlie, Chaplin, Chuckles";
        return File(new System.Text.UTF8Encoding().GetBytes(csv), "text/csv", "Report123.csv");
    }
Biff MaGriff
fuente
¿Cómo manejaríamos las cadenas que contienen comas? Intenté usar comillas dobles como calificadores de texto, pero no parece funcionar.
Mike Cole
1
@mmssaann Esa es la belleza, no usa javascript. Simplemente establezca el href de su etiqueta de anclaje en la acción. <a href="ControllerName/ActionName">Download CSV</a>
Biff MaGriff
1
He configurado el href para la etiqueta de anclaje. Funciona bien. Sin embargo, todavía puedo ver que la página completa está publicada. ¿Hay alguna forma de restringir la devolución de datos?
mmssaann
1
@mmssaann Debe hacer una nueva pregunta con detalles sobre su configuración particular.
Biff MaGriff
1
Utilizo tu forma de crear CSV de descarga, todo parece estar bien, depuro, va al controlador. ¿Pero el navegador no muestra ningún signo de archivo de descarga? ¿Crees que está pasando, necesito cambiar Web.config o algo?
zquanghoangz
13

Con MVC, simplemente puede devolver un archivo como este:

public ActionResult ExportData()
{
    System.IO.FileInfo exportFile = //create your ExportFile
    return File(exportFile.FullName, "text/csv", string.Format("Export-{0}.csv", DateTime.Now.ToString("yyyyMMdd-HHmmss")));
}
yan.kun
fuente
8
¿Realmente desea crear un montón de archivos en el servidor web? ¿Qué hay de limpiarlos? ¿Y la seguridad?
chris
@chris ¿eso no crea archivos en la memoria del servidor en lugar de en el sistema de archivos?
Galdin
Utilizo tu forma de crear CSV de descarga, todo parece estar bien, depuro, va al controlador. ¿Pero el navegador no muestra ningún signo de archivo de descarga? ¿Crees que pasa, necesito cambiar Web.config o algo?
zquanghoangz
7

Además de la respuesta de Biff MaGriff. Para exportar el archivo usando JQuery, redirija al usuario a una nueva página.

$('#btn_export').click(function () {
    window.location.href = 'NewsLetter/Export';
});
Harminder
fuente
5

¿Qué pasa si te deshaces del guionista?

        Response.Clear();
        Response.AddHeader("Content-Disposition", "attachment; filename=adressenbestand.csv");
        Response.ContentType = "text/csv";
        //write the header
        Response.Write(String.Format("{0},{1},{2},{3}", CMSMessages.EmailAddress, CMSMessages.Gender, CMSMessages.FirstName, CMSMessages.LastName));

        //write every subscriber to the file
        var resourceManager = new ResourceManager(typeof(CMSMessages));
        foreach (var record in filterRecords.Select(x => x.First().Subscriber))
        {
            Response.Write(String.Format("{0},{1},{2},{3}", record.EmailAddress, record.Gender.HasValue ? resourceManager.GetString(record.Gender.ToString()) : "", record.FirstName, record.LastName));
        }

        Response.End();
chris
fuente
no, eso tampoco hace la diferencia. Ya lo resolví de una manera diferente. Ver mi edición. ¡Gracias por tu ayuda de todos modos!
Gerard
3

Con respecto a Biff, aquí hay algunos ajustes que me permiten usar el método para rebotar CSV de jQuery / Post en el servidor y regresar como un mensaje CSV al usuario.

    [Themed(false)]
    public FileContentResult DownloadCSV()
    {

        var csvStringData = new StreamReader(Request.InputStream).ReadToEnd();

        csvStringData = Uri.UnescapeDataString(csvStringData.Replace("mydata=", ""));

        return File(new System.Text.UTF8Encoding().GetBytes(csvStringData), "text/csv", "report.csv");
    }

Necesitará la línea unescape si está presionando esto desde un formulario con un código como el siguiente,

    var input = $("<input>").attr("type", "hidden").attr("name", "mydata").val(data);
    $('#downloadForm').append($(input));
    $("#downloadForm").submit();
MonsCamus
fuente
3

Desde un botón en la vista, llame a .click (llame a algún script java). Desde allí, llame al método del controlador mediante window.location.href = 'Controlador / Método';

En el controlador, llame a la base de datos y obtenga la tabla de datos o llame a algún método, obtenga los datos de la tabla de la base de datos a una tabla de datos y luego haga lo siguiente,

using (DataTable dt = new DataTable())
                        {
                            sda.Fill(dt);
                            //Build the CSV file data as a Comma separated string.
                            string csv = string.Empty;
                            foreach (DataColumn column in dt.Columns)
                            {
                                //Add the Header row for CSV file.
                                csv += column.ColumnName + ',';
                            }
                            //Add new line.
                            csv += "\r\n";
                            foreach (DataRow row in dt.Rows)
                            {
                                foreach (DataColumn column in dt.Columns)
                                {
                                    //Add the Data rows.
                                    csv += row[column.ColumnName].ToString().Replace(",", ";") + ',';
                                }
                                //Add new line.
                                csv += "\r\n";
                             }
                             //Download the CSV file.
                             Response.Clear();
                             Response.Buffer = true;
                             Response.AddHeader("content-disposition", "attachment;filename=SqlExport"+DateTime.Now+".csv");
                             Response.Charset = "";
                             //Response.ContentType = "application/text";
                             Response.ContentType = "application/x-msexcel";
                             Response.Output.Write(csv);
                             Response.Flush();
                             Response.End();
                           }
Ashrughna
fuente
1

Incluso si ha resuelto su problema, aquí hay otro intento de exportar csv usando mvc.

return new FileStreamResult(fileStream, "text/csv") { FileDownloadName = fileDownloadName };
Sandip
fuente
0

Creo que te has olvidado de usar

  Response.Flush();

debajo

  Response.Write(sw);

por favor, compruebe

Deepan Raj
fuente
-3

Crear archivo de Excel simple en MVC 4

public ActionResult results () {return File (nuevo System.Text.UTF8Encoding (). GetBytes ("cadena de datos"), "application / csv", "filename.csv"); }

seguro B
fuente
Ésta no es una buena respuesta. Consulte ¿Cómo escribo una buena respuesta?
Clijsters
Es una buena respuesta. Está mal formateado y duplica la mejor respuesta que se publicó 6 años antes. : D
Caltor