91

I am trying to export a list to a CSV file. I got it all working up to the point I want to write to file to the response stream. This doesn't do anything.

Here is my code:

Call the the method from the page.

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

The code in the controller is as follows:

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

But after Response.Write(sw) nothing is happening. Is it even possible to save a file this way?

Regards

Edit
The response headers I see when I click the button are:

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

Which seem OK to me..

Edit
I got rid of the jQuery part en replaced it by an hyperlink and this is working fine for me now:

<a class="export" href="NewsLetter/Export">exporteren</a>
2
  • 1
    Maybe this question on SO helps: stackoverflow.com/questions/4522590/… Commented Jan 12, 2011 at 13:29
  • 1
    Could you document your answer as an actual answer rather than editing the question please. Commented Mar 10, 2020 at 11:22

8 Answers 8

261

yan.kun was on the right track but this is much much easier.

    public FileContentResult DownloadCSV()
    {
        string csv = "Charlie, Chaplin, Chuckles";
        return File(new System.Text.UTF8Encoding().GetBytes(csv), "text/csv", "Report123.csv");
    }
Sign up to request clarification or add additional context in comments.

9 Comments

How would we handle strings that contain commas? I tried using double quotes as text qualifiers but it doesn't seem to work.
@mmssaann That's the beauty of it, you don't use javascript. You just set the href of your anchor tag to the action. <a href="ControllerName/ActionName">Download CSV</a>
I have set the href for anchor tag. It is working fine. However the I can still see the entire page is posted back. is there a way to restrict the postback?
@mmssaann You should ask a new question with details about your particular setup.
I use your way to create download CSV, everything seems ok, I debug, it goes to the controller. But the browser doesn't show any sign of download file? Do you think what's happen, I need to change Web.config or something?
|
14

With MVC you can simply return a file like this:

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

3 Comments

Do you really want to create a bunch of files on the web server? What about cleaning them up? What about security?
@chris doesn't that create files in the server's memory rather than the filesystem?
I use your way to create download CSV, everything seems ok, I debug, it goes to the controller. But the browser doesn't show any sign of download file? Do you think what's happen, I need to change Web.config or something?
7

In addition to Biff MaGriff's answer. To export the file using JQuery, redirect the user to a new page.

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

Comments

5

What happens if you get rid of the 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();

1 Comment

nope that doesn't make a difference either. I got it solved allready in a different way. See my edit. Thanks for your help anyway!
3

Respect to Biff, here's a few tweaks that let me use the method to bounce CSV from jQuery/Post against the server and come back as a CSV prompt to the user.

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

You'll need the unescape line if you are hitting this from a form with code like the following,

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

Comments

3

From a button in view call .click(call some java script). From there call controller method by window.location.href = 'Controller/Method';

In controller either do the database call and get the datatable or call some method get the data from database table to a datatable and then do following,

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

Comments

1

Even if you have resolved your issue, here is another one try to export csv using mvc.

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

Comments

0

I Think you have forgot to use

  Response.Flush();

under

  Response.Write(sw);

please check

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.