Esporta in CSV utilizzando MVC, C # e jQuery


85

Sto cercando di esportare un elenco in un file CSV. Ho funzionato tutto fino al punto in cui voglio scrivere su file nel flusso di risposta. Questo non fa niente.

Ecco il mio codice:

Chiama il metodo dalla pagina.

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

Il codice nel controller è il seguente:

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

Ma dopo Response.Write(sw)non sta succedendo niente. È anche possibile salvare un file in questo modo?

Saluti

Modifica
Le intestazioni delle risposte che vedo quando faccio clic sul pulsante sono:

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

Il che mi sembra OK ..

Modifica
Mi sono sbarazzato della parte jQuery e l'ho sostituita con un collegamento ipertestuale e ora funziona bene per me:

<a class="export" href="NewsLetter/Export">exporteren</a>

1
Forse questa domanda su SO aiuta: stackoverflow.com/questions/4522590/…
Rob il

Potresti documentare la tua risposta come una risposta effettiva piuttosto che modificare la domanda per favore.
Caltor

Risposte:


250

yan.kun era sulla strada giusta ma questo è molto più facile.

    public FileContentResult DownloadCSV()
    {
        string csv = "Charlie, Chaplin, Chuckles";
        return File(new System.Text.UTF8Encoding().GetBytes(csv), "text/csv", "Report123.csv");
    }

Come gestiremmo le stringhe che contengono virgole? Ho provato a utilizzare le virgolette doppie come qualificatori di testo ma non sembra funzionare.
Mike Cole

1
@mmssaann Questo è il bello, non usi javascript. Devi solo impostare l'href del tuo anchor tag sull'azione. <a href="ControllerName/ActionName">Download CSV</a>
Biff MaGriff

1
Ho impostato l'href per il tag di ancoraggio. Funziona bene. Tuttavia, posso ancora vedere l'intera pagina è stata postata. c'è un modo per limitare il postback?
mmssaann

1
@mmssaann Dovresti porre una nuova domanda con i dettagli sulla tua particolare configurazione.
Biff MaGriff

1
Io uso il tuo modo per creare download CSV, sembra tutto ok, eseguo il debug, va al controller. Ma il browser non mostra alcun segno di download del file? Pensi che cosa sia successo, devo cambiare Web.config o qualcosa del genere?
zquanghoangz

13

Con MVC puoi semplicemente restituire un file come questo:

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")));
}

8
Vuoi davvero creare un mucchio di file sul server web? Che ne dici di ripulirli? E la sicurezza?
chris

@chris non crea file nella memoria del server piuttosto che nel filesystem?
galdin

Io uso il tuo modo per creare download CSV, sembra tutto ok, eseguo il debug, va al controller. Ma il browser non mostra alcun segno di download del file? Pensi che cosa sia successo, devo cambiare Web.config o qualcosa del genere?
zquanghoangz

7

Oltre alla risposta di Biff MaGriff. Per esportare il file utilizzando JQuery, reindirizza l'utente a una nuova pagina.

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

5

Cosa succede se ti sbarazzi dello stringwriter:

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

no, anche questo non fa differenza. L'ho già risolto in un modo diverso. Vedi la mia modifica. Grazie comunque per il tuo aiuto!
Gerard

3

Rispetto a Biff, ecco alcune modifiche che mi consentono di utilizzare il metodo per rimbalzare CSV da jQuery / Post contro il server e tornare come prompt CSV all'utente.

    [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");
    }

Avrai bisogno della riga unescape se la stai premendo da un modulo con codice come il seguente,

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

3

Da un pulsante in vista, chiama .click (chiama alcuni script java). Da lì chiama il metodo del controller tramite window.location.href = 'Controller / Method';

Nel controller eseguire la chiamata al database e ottenere il datatable o chiamare un metodo per ottenere i dati dalla tabella del database a un datatable e quindi eseguire le operazioni seguenti,

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

1

Anche se hai risolto il tuo problema, ecco un altro tentativo di esportare csv usando mvc.

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

0

Penso che ti sei dimenticato di usare

  Response.Flush();

sotto

  Response.Write(sw);

si prega di controllare


-3

Semplice file excel creato in mvc 4

public ActionResult results () {return File (new System.Text.UTF8Encoding (). GetBytes ("string data"), "application / csv", "filename.csv"); }


Questa non è una buona risposta. Fare riferimento a Come scrivere una buona risposta?
Clijsters

È una buona risposta. È solo mal formattato e duplica la migliore risposta che è stata pubblicata 6 anni prima. : D
Caltor
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.