Eksportuj do CSV przy użyciu MVC, C # i jQuery

85

Próbuję wyeksportować listę do pliku CSV. Wszystko działa do momentu, w którym chcę zapisać do pliku w strumieniu odpowiedzi. To nic nie daje.

Oto mój kod:

Wywołaj metodę ze strony.

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

Kod w kontrolerze jest następujący:

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

Ale po Response.Write(sw)nic się nie dzieje. Czy w ogóle można zapisać plik w ten sposób?

pozdrowienia

Edytuj
Nagłówki odpowiedzi, które widzę po kliknięciu przycisku, to:

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

Co wydaje mi się w porządku ...

Edytuj
Pozbyłem się części jQuery i zastąpiłem ją hiperłączem i teraz działa dobrze:

<a class="export" href="NewsLetter/Export">exporteren</a>
Gerard
źródło
1
Może to pytanie na temat SO pomoże: stackoverflow.com/questions/4522590/…
Rob
Czy mógłbyś udokumentować swoją odpowiedź jako rzeczywistą odpowiedź, zamiast edytować pytanie?
Caltor

Odpowiedzi:

250

yan.kun był na dobrej drodze, ale jest to znacznie łatwiejsze.

    public FileContentResult DownloadCSV()
    {
        string csv = "Charlie, Chaplin, Chuckles";
        return File(new System.Text.UTF8Encoding().GetBytes(csv), "text/csv", "Report123.csv");
    }
Biff MaGriff
źródło
Jak poradzilibyśmy sobie z napisami zawierającymi przecinki? Próbowałem używać podwójnych cudzysłowów jako kwalifikatorów tekstu, ale wydaje się, że nie działa.
Mike Cole,
1
@mmssaann Na tym polega piękno, nie używasz javascript. Po prostu ustaw href swojego znacznika kotwicy na akcję. <a href="ControllerName/ActionName">Download CSV</a>
Biff MaGriff,
1
Ustawiłem href dla tagu kotwicy. Działa dobrze. Jednak nadal widzę, że cała strona została wysłana z powrotem. czy istnieje sposób na ograniczenie ogłaszania zwrotnego?
mmssaann
1
@mmssaann Powinieneś zadać nowe pytanie ze szczegółami dotyczącymi twojej konkretnej konfiguracji.
Biff MaGriff
1
Używam twojego sposobu, aby stworzyć plik CSV do pobrania, wszystko wydaje się ok, debuguję, idzie do kontrolera. Ale przeglądarka nie pokazuje żadnych śladów pobierania pliku? Myślisz, że co się stało, muszę zmienić Web.config czy coś?
zquanghoangz
13

Dzięki MVC możesz po prostu zwrócić plik taki jak ten:

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
źródło
8
Czy na pewno chcesz utworzyć kilka plików na serwerze WWW? A co z ich czyszczeniem? A co z bezpieczeństwem?
chris
@chris czy to nie tworzy plików w pamięci serwera, a nie w systemie plików?
galdin
Używam twojego sposobu, aby stworzyć plik CSV do pobrania, wszystko wydaje się ok, debuguję, idzie do kontrolera. Ale przeglądarka nie pokazuje żadnych śladów pobierania pliku? Myślisz, że co się stało, muszę zmienić Web.config czy coś?
zquanghoangz
7

Oprócz odpowiedzi Biff MaGriffa. Aby wyeksportować plik za pomocą JQuery, przekieruj użytkownika na nową stronę.

$('#btn_export').click(function () {
    window.location.href = 'NewsLetter/Export';
});
Harminder
źródło
5

Co się stanie, jeśli pozbędziesz się stringwritera:

        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
źródło
nie, to też nie robi różnicy. Już to rozwiązałem w inny sposób. Zobacz moją edycję. Mimo wszystko, dziękuję za twoją pomoc!
Gerard
3

Szacunek dla Biff, oto kilka poprawek, które pozwalają mi użyć metody do odbijania CSV z jQuery / Post na serwerze i powrotu jako zachęta CSV do użytkownika.

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

Będziesz potrzebował linii unescape, jeśli klikasz to z formularza z kodem podobnym do poniższego,

    var input = $("<input>").attr("type", "hidden").attr("name", "mydata").val(data);
    $('#downloadForm').append($(input));
    $("#downloadForm").submit();
MonsCamus
źródło
3

Z przycisku w widoku wywołaj .click (wywołaj skrypt java). Stamtąd wywołaj metodę kontrolera przez window.location.href = 'Controller / Method';

W kontrolerze albo wywołaj bazę danych i pobierz datatable, albo wywołaj jakąś metodę, pobierz dane z tabeli bazy danych do datatable, a następnie wykonaj następujące czynności,

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
źródło
1

Nawet jeśli rozwiązałeś problem, oto kolejna próba wyeksportowania csv za pomocą mvc.

return new FileStreamResult(fileStream, "text/csv") { FileDownloadName = fileDownloadName };
Sandip
źródło
0

Myślę, że zapomniałeś użyć

  Response.Flush();

pod

  Response.Write(sw);

proszę sprawdzić

Deepan Raj
źródło
-3

Prosty plik Excela tworzony w MVC 4

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

suresh B.
źródło
To nie jest dobra odpowiedź. Zobacz Jak napisać dobrą odpowiedź?
Clijsters
To dobra odpowiedź. Jest po prostu źle sformatowany i powiela najlepszą odpowiedź, która została opublikowana 6 lat wcześniej. : D
Caltor,