0

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)

5
  • In string "attachment;filename="+sch.SchoolName+".csv", do not concatenate the file name, instead take complete string into variable and pass here. Commented Jan 10, 2018 at 7:23
  • I tried this, var fileName = sch.SchoolName; response.AddHeader("content-disposition", "attachment;filename="+fileName+".csv"); but this saves it as .txt again. plus, instead of taking the full name as stored in db > ABC - O Levels it only takes ABC Commented Jan 10, 2018 at 7:30
  • I'm not sure, but does the schoolname contain spaces or some illegal filename chars? What happens, if your school name is "Logs"? Commented Jan 10, 2018 at 7:44
  • @Oliver "Logs" is the name of the table and the school name is ABC - O Levels in db. Commented Jan 10, 2018 at 7:45
  • It is just for testing the response header. Does your string concatenation in response.AddHeader() work if the variable sch.SchoolName has the value Logs (no spaces, no special chars, etc.). If that works than isn't your code the problem, but the data it contains. Commented Jan 10, 2018 at 7:51

3 Answers 3

1

Below is the solution of this error

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

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

Sign up to request clarification or add additional context in comments.

1 Comment

Tried this, still the same.
1

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

4 Comments

with a missing ) at the end, sadly this does not work either. saves the file as .txt
var fileName = sch.SchoolName + "-" + sch.SchoolBranch + "-" + machineNumber; var attachmentValue = string.Format("attachment; filename={0}.csv",fileName); why does this saves only the schoolName and not the rest? I want it to be like ABC-1-1 but it takes only ABC
Check the values of sch.SchoolBranch and machineNumber. They might be empty or null that is why it is behaving like this.
Try this then response.AddHeader("Content-Disposition", "attachment; filename=\"" + fileName + "\"");
0

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.

1 Comment

kindly see the updated ques. it is saving as .csv now but I need to make sure it takes the full name and furthermore, any workaround for the snippet commented above?

Your Answer

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