【问题标题】:Multiple .csv downloads from a single table. ASP.NET MVC从单个表下载多个 .csv。 ASP.NET MVC
【发布时间】:2018-01-10 07:09:46
【问题描述】:

下面的 sn-p 可以很好地将 sql 表下载到.csv 但是不起作用的是,当我尝试像这样更改动态地给出文件名时;

代替:

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

我用:

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

它将文件保存为.txt 而不是.csv 为什么会这样?

此外,为了清晰起见,我有一个表格,它根据MacNum 列将记录彼此分开。我正在尝试从同一个表中生成两个不同的.csv 文件,但文件名不同,如果我取消注释下面的部分(注释一个),它会抛出一个"Cannot send headers" 异常。

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

更新: 下面是它正在拍摄的fileName 的照片,但是当它只用whs 保存时。

此外,如何在同一张表中为另一所学校再次运行相同的代码? (上面sn-p中的注释代码)

【问题讨论】:

  • 在字符串“attachment;filename="+sch.SchoolName+".csv”中,不要连接文件名,而是将完整的字符串放入变量并传递到这里。
  • 我试过了,var fileName = sch.SchoolName; response.AddHeader("content-disposition", "attachment;filename="+fileName+".csv"); 但这又将它保存为.txt。另外,而不是将全名存储在 db > ABC - O Levels 它只需要 ABC
  • 我不确定,但学校名称是否包含空格或某些非法文件名字符?如果您的学校名称是“Logs”,会发生什么?
  • @Oliver "Logs" 是表名,学校名是ABC - O Levels in db。
  • 只是为了测试响应头。如果变量sch.SchoolName 的值为Logs(没有空格、没有特殊字符等),那么response.AddHeader() 中的字符串连接是否有效。如果这有效,那么问题不是您的代码,而是它包含的数据。

标签: c# asp.net-mvc csv


【解决方案1】:

下面是这个错误的解决方法

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

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

【讨论】:

  • 试过了,还是一样。
【解决方案2】:

尝试这样使用

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

或者试试下面的

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

【讨论】:

  • 最后缺少),遗憾的是这也不起作用。将文件保存为.txt
  • var fileName = sch.SchoolName + "-" + sch.SchoolBranch + "-" + machineNumber; var attachmentValue = string.Format("attachment; filename={0}.csv",fileName); 为什么只保存 schoolName 而不是其余的?我希望它像 ABC-1-1 但它只需要 ABC
  • 检查sch.SchoolBranchmachineNumber的值。它们可能为空或 null,这就是它的行为方式。
  • 试试这个然后response.AddHeader("Content-Disposition", "attachment; filename=\"" + fileName + "\"");
【解决方案3】:

回答第一个问题为什么您的文件名不起作用

在阅读the spec 之后,您似乎必须将文件名设置为双引号:

Content-Disposition:附件;文件名="文件名.jpg"

文件名

后跟一个字符串,包含传输文件的原始名称。文件名始终是可选的,应用程序不能盲目使用:路径信息应该被剥离,并且应该转换为服务器文件系统规则。该参数主要提供指示性信息。当与 Content-Disposition: attachment 结合使用时,它被用作呈现给用户的最终“另存为”对话框的默认文件名。

所以你应该在你的字符串中添加双引号:

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

回答第二个问题为什么不能发送第二个文件

如果您取消注释第二个代码块,它会失败,因为对于一个请求,您只能发回一个响应(也就是一个文件)。当您在活动代码中调用 response.End() 并随后在同一响应上调用其他方法时(即使您通过另一个变量名请求它),您会收到错误,因为流已经关闭。

如果你认为你现在可以很聪明并且根本不打电话给response.End(),它也不会起作用,因为在这种情况下你只会收到一个文件,其中包含你想要获取的两个文件的数据。

所以有一个简单的规则:一个请求导致一个响应,其中包含一个文件。为了实现您的目标,现在有两种可能的解决方案:

  1. 您仍然返回一个文件,但它是某种包含多个文件的容器文件。您肯定知道的一个突出示例是 .zip 文件。
  2. 您采用您的客户端和服务器。服务器不发送文件的内容。相反,它返回可用文件名的列表。然后客户端使用所需的文件名打开列表中每个条目的请求,您可以分别发回每个文件。

【讨论】:

  • 请查看更新后的问题。它现在保存为.csv,但我需要确保它采用全名,此外,上面评论的 sn-p 的任何解决方法?
猜你喜欢
  • 2021-09-06
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2021-11-03
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多