Exportieren Sie mit MVC, C # und jQuery nach CSV

84

Ich versuche, eine Liste in eine CSV-Datei zu exportieren. Ich habe alles bis zu dem Punkt zum Laufen gebracht, an dem ich in eine Datei in den Antwortstrom schreiben möchte. Das macht nichts.

Hier ist mein Code:

Rufen Sie die Methode von der Seite auf.

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

Der Code in der Steuerung lautet wie folgt:

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

Aber nachdem Response.Write(sw)nichts passiert ist. Ist es überhaupt möglich, eine Datei auf diese Weise zu speichern?

Grüße

Bearbeiten
Die Antwort-Header, die ich sehe, wenn ich auf die Schaltfläche klicke, sind:

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

Welches scheint mir in Ordnung zu sein ..

Bearbeiten
Ich habe den jQuery-Teil entfernt und ihn durch einen Hyperlink ersetzt, und das funktioniert jetzt gut für mich:

<a class="export" href="NewsLetter/Export">exporteren</a>
Gerard
quelle
1
Vielleicht hilft diese Frage auf SO: stackoverflow.com/questions/4522590/…
Rob
Könnten Sie Ihre Antwort als tatsächliche Antwort dokumentieren, anstatt die Frage zu bearbeiten?
Caltor

Antworten:

248

yan.kun war auf dem richtigen Weg, aber das ist viel einfacher.

    public FileContentResult DownloadCSV()
    {
        string csv = "Charlie, Chaplin, Chuckles";
        return File(new System.Text.UTF8Encoding().GetBytes(csv), "text/csv", "Report123.csv");
    }
Biff MaGriff
quelle
Wie würden wir mit Zeichenfolgen umgehen, die Kommas enthalten? Ich habe versucht, doppelte Anführungszeichen als Textqualifizierer zu verwenden, aber es scheint nicht zu funktionieren.
Mike Cole
1
@mmssaann Das ist das Schöne daran, du verwendest kein Javascript. Sie setzen einfach die href Ihres Ankertags auf die Aktion. <a href="ControllerName/ActionName">Download CSV</a>
Biff MaGriff
1
Ich habe die href für Anker-Tag gesetzt. Es funktioniert gut. Allerdings kann ich immer noch sehen, dass die gesamte Seite zurück gepostet wird. Gibt es eine Möglichkeit, das Postback einzuschränken?
mmssaann
1
@mmssaann Sie sollten eine neue Frage mit Details zu Ihrem speziellen Setup stellen.
Biff MaGriff
1
Ich benutze deine Art, um Download-CSV zu erstellen, alles scheint in Ordnung zu sein, ich debugge, es geht an den Controller. Aber der Browser zeigt keine Anzeichen einer Download-Datei? Denken Sie, was passiert ist, ich muss Web.config ändern oder so?
Zquanghoangz
13

Mit MVC können Sie einfach eine Datei wie folgt zurückgeben:

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
quelle
8
Möchten Sie wirklich eine Reihe von Dateien auf dem Webserver erstellen? Was ist mit dem Aufräumen? Was ist mit Sicherheit?
chris
@chris erstellt das nicht Dateien im Speicher des Servers und nicht im Dateisystem?
Galdin
Ich benutze deine Art, um Download-CSV zu erstellen, alles scheint in Ordnung zu sein, ich debugge, es geht an den Controller. Aber der Browser zeigt keine Anzeichen einer Download-Datei? Denken Sie, was passiert ist, ich muss Web.config ändern oder so?
Zquanghoangz
7

Neben der Antwort von Biff MaGriff. Um die Datei mit JQuery zu exportieren, leiten Sie den Benutzer auf eine neue Seite um.

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

Was passiert, wenn Sie den Stringwriter loswerden:

        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
quelle
Nein, das macht auch keinen Unterschied. Ich habe es schon anders gelöst. Siehe meine Bearbeitung. Trotzdem danke für deine Hilfe!
Gerard
3

In Bezug auf Biff, hier sind einige Verbesserungen, mit denen ich die Methode verwenden kann, um CSV von jQuery / Post auf den Server zu übertragen und als CSV-Eingabeaufforderung an den Benutzer zurückzukehren.

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

Sie benötigen die Unescape-Zeile, wenn Sie diese aus einem Formular mit Code wie dem folgenden treffen:

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

Rufen Sie über eine Schaltfläche in der Ansicht .click auf (rufen Sie ein Java-Skript auf). Von dort aus rufen Sie die Controller-Methode mit window.location.href = 'Controller / Method' auf.

Führen Sie im Controller entweder den Datenbankaufruf aus und rufen Sie die Datentabelle ab, oder rufen Sie eine Methode auf, um die Daten aus der Datenbanktabelle in eine Datentabelle zu übertragen, und führen Sie dann die folgenden Schritte aus:

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
quelle
1

Auch wenn Sie Ihr Problem behoben haben, versuchen Sie hier noch einmal, csv mit mvc zu exportieren.

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

Ich denke du hast vergessen zu benutzen

  Response.Flush();

unter

  Response.Write(sw);

bitte prüfen

Deepan Raj
quelle
-3

Einfache Excel-Datei in MVC 4 erstellen

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

suresh B.
quelle
Dies ist keine gute Antwort. Weitere Informationen finden Sie unter Wie schreibe ich eine gute Antwort?
Clijsters
Das ist eine gute Antwort. Es ist nur schlecht formatiert und dupliziert die beste Antwort, die 6 Jahre zuvor veröffentlicht wurde. : D
Caltor