user9046719
user9046719

Reputation:

Multiple .csv downloads from a single table. ASP.NET MVC

The below snippet works fine to download a sql table to .csv however what does not work is that, when I try to give the file name dynamically like this change;

Instead of:

response.AddHeader("content-disposition", "attachment;filename=Logs.csv");

I use:

response.AddHeader("content-disposition", "attachment;filename="+sch.SchoolName+".csv");

It saves the file as .txt and not .csv why is that so?

Furthermore, to be crystal, I have a table which separates the records from eachother on the basis of the column MacNum. I am trying to generate two different .csv files from the same table but with different file names, If I uncomment the below part (commented one) it throws me a "Cannot send headers" exception.

 public void ExportCSV_CloudLogs()
        {
            School sch = (from sc in db.Schools
                          where sc.MacNum == 1.ToString()
                          select sc).FirstOrDefault();
            var sb = new StringBuilder();
            var list  = (from o in db.Logs where o.MacNum == 1
                         select o).ToList();
            sb.AppendFormat("{0},{1},{2},{3},{4},{5},{6},{7},{8},{9},{10}", "No", "Name", "Time", "Mode", "Ex", "Type", "SId", "Work", "sDate", "MachineNum", Environment.NewLine);
            foreach (var item in list)
            {
                sb.AppendFormat("{0},{1},{2},{3},{4},{5},{6},{7},{8},{9},{10}", item.No, item.Name, item.Time, item.Mode, item.Ex, item.Type, item.SId, item.Work, item.Date, item.MacNum, Environment.NewLine);
            }
            //Get Current Response  
            var response = System.Web.HttpContext.Current.Response;
            response.BufferOutput = true;
            response.Clear();
            response.ClearHeaders();
            response.ContentEncoding = Encoding.Unicode;
            response.AddHeader("content-disposition", "attachment;filename="+sch.SchoolName+".csv");
            response.ContentType = "text/plain";
            response.Write(sb.ToString());
            response.End();

            //School sch2 = (from sc in db.Schools
            //               where sc.MacNum == 2.ToString()
            //               select sc).FirstOrDefault();
            //var sb2 = new StringBuilder();
            //var list2 = (from o in db.Logs
            //            where o.MacNum == 2
            //            select o).ToList();
            //sb2.AppendFormat("{0},{1},{2},{3},{4},{5},{6},{7},{8},{9},{10}", "No", "Name", "Time", "Mode", "Ex", "Type", "SId", "Work", "sDate", "MacNum", Environment.NewLine);
            //foreach (var item in list2)
            //{
            //    sb2.AppendFormat("{0},{1},{2},{3},{4},{5},{6},{7},{8},{9},{10}", item.No, item.Name, item.Time, item.Mode, item.Exception, item.Type, item.SId, item.Work, item.Date, item.MacNum, Environment.NewLine);
            //}
            ////Get Current Response  
            //var response2 = System.Web.HttpContext.Current.Response;
            //response2.BufferOutput = true;
            //response2.Clear();
            //response2.ClearHeaders();
            //response2.ContentEncoding = Encoding.Unicode;
            //response2.AddHeader("content-disposition", "attachment;filename="+sch.SchoolName+".CSV ");
            //response2.ContentType = "text/plain";
            //response2.Write(sb2.ToString());
            //response2.End();
        }

UPDATE: below is the picture of the fileName it is taking but when it only saves it with whs.

enter image description here

Furthermore, how do I run the same code again for another school in the same table? (the commented code in the above snippet)

Upvotes: 0

Views: 746

Answers (3)

Oliver
Oliver

Reputation: 45101

Answer to first question why your filename doesn't work

After reading the spec it seems that you have to set your filename into double quotes:

Content-Disposition: attachment; filename="filename.jpg"

filename

Is followed by a string containing the original name of the file transmitted. The filename is always optional and must not be used blindly by the application: path information should be stripped, and conversion to the server file system rules should be done. This parameter provides mostly indicative information. When used in combination with Content-Disposition: attachment, it is used as the default filename for an eventual 'Save As" dialog presented to the user.

So you should add double quotes to your string:

response.AddHeader("content-disposition", "attachment;filename=\"" + sch.SchoolName + ".csv\"");

Answer to second question why you cannot send a second file

If you uncomment your second code block, it fails, cause for one request you can only send back one response (aka one file). When you call response.End() in your active code and afterwards call other methods on the same response (even if you request it through another variable name) you got errors because the stream has already been closed.

If you think you can be smart now and simply not call response.End() it won't work either, because in that case you receive only one file which contains the data of both files you like to get.

So there is a simple rule: One request leads to one response, which contains one file. To accomplish your goal, there are now two possible solution:

  1. You still return one file, but that is some kind of container file that holds multiple files. One prominent example you surely know would be a .zip file.
  2. You adopt your client and server. The server doesn't send the content of the file. Instead it returns a list of available filenames. Then the client opens a request for each entry in the list with the desired filename an you can send back each file separately.

Upvotes: 0

Nitesh Kumar
Nitesh Kumar

Reputation: 1774

Try to use like this

response.AddHeader("content-disposition", string.Format("attachment;filename={0}.csv", sch.SchoolName));

Or try the following

var attachmentValue = string.Format("attachment; filename={0}.csv", sch.SchoolName);
response.AddHeader("content-disposition", attachmentValue);
response.ContentType = "text/csv";

Upvotes: 1

Vijay Raheja
Vijay Raheja

Reputation: 290

Below is the solution of this error

var fileDetail ="attachment;filename="+sch.SchoolName+".csv";

response.AddHeader("content-disposition", fileDetail);

Upvotes: 1

Related Questions