MVC Action不返回csv文件。 ERR_RESPONSE_HEADERS_MULTIPLE_CONTENT_DISPOSITION

时间:2016-08-27 11:40:01

标签: asp.net asp.net-mvc csv

我想从数据库中获取数据并将其显示在CSV文件中。以下是我从db获取数据的代码。

public ActionResult GetTNStateUnemploymentReport(int quarter, int year, int payrollState, long? fromClientId, long? toClientId, string fromClient, string toClient)
{
//if (fromClient == "" && toClient == "")
//{
//    fromClientId = 0;
//    toClientId = 0;
//}

string quarterMonths = "";
if (quarter == 1)
    quarterMonths = "Jan, Feb, Mar";
else if (quarter == 2)
    quarterMonths = "Apr, May, Jun";
else if (quarter == 3)
    quarterMonths = "Jul, Aug, Sep";
else if (quarter == 4)
    quarterMonths = "Oct, Nov, Dec";

var modelList = new PayrollHelper().GetTNStateUnemploymentReport(quarter, year, fromClientId ?? 0, toClientId ?? 0);
var csv = new System.Text.StringBuilder();
foreach (var model in modelList)
{
    csv.Append(string.Format("{0}{1}", model.StringData, Environment.NewLine));
}

return new CSVResult
{
    FileName = "TN_" + quarterMonths + "_" + year.ToString() + ".csv",
    Content = csv.ToString()
};

以下是我用于创建CSV文件的CSVResult课程。

public class CSVResult: ActionResult
{
    public string FileName { get; set; }
    public string Content { get; set; }

    public override void ExecuteResult(ControllerContext context)
    {
        context.HttpContext.Response.Buffer = true;
        context.HttpContext.Response.Clear();
        context.HttpContext.Response.AddHeader("content-disposition", "attachment; filename=" + FileName);
        context.HttpContext.Response.ContentType = "application/csv;charset=utf-8";
        context.HttpContext.Response.Write(Content);
        context.HttpContext.Response.End();
    }
}

我收到以下错误:

  

本地主机发出无效响应   ERR_RESPONSE_HEADERS_MULTIPLE_CONTENT_DISPOSITION。

我有另一个报告使用上面提到的ExecuteResult方法创建CSV文件并且工作正常,但当前的报告没有。

2 个答案:

答案 0 :(得分:1)

为什么不使用从FileResult派生的标准结果?

FileResult Class

3个具体课程中的一个应该做你想要的。如果您自己编写ActionResult,那么您可以编写正确的代码。

答案 1 :(得分:1)

根据您的代码"TN_" + quarterMonths + "_" + year.ToString() + ".csv",文件名将如下所示

"TN_Jul, Aug, Sep_2016.csv"

,基于.AddHeader("content-disposition", "attachment; filename=" + FileName)会导致内容处理看起来像这样

"Content-Disposition: attachment; filename=TN_Jul, Aug, Sep_2016.csv"

生成内容处置时文件名中的逗号和空格将导致某些浏览器出现问题。

现在有几种方法可以解决这个问题。

1)您可以更改生成文件名的方式,以使用下划线(,)替换空格和逗号(_)

例如,

而不是

quarterMonths = "Jan, Feb, Mar";

将其更改为

quarterMonths = "Jan_Feb_Mar";

导致文件名看起来像

"TN_Jul_Aug_Sep_2016.csv"

2)您还可以确保将文件名括在""(双引号)

所以而不是

.AddHeader("content-disposition", "attachment; filename=" + FileName)

将其更改为

.AddHeader("content-disposition", "attachment; filename=\"" + FileName + "\"");

.AddHeader("content-disposition", string.Format("attachment; filename=\"{0}\"", FileName));

更新:

使用System.Web.Mvc.FileResult源代码中的提示您可以重写CsvResult以允许我上面提到的建议更改。

public class CsvResult : ActionResult {
    private const string CONTENT_TYPE = "application/csv;charset=utf-8";
    private string filename;

    public CsvResult() {
        System.Net.Http.Headers.MediaTypeHeaderValue headerValue = null;
        if (System.Net.Http.Headers.MediaTypeHeaderValue.TryParse(CONTENT_TYPE, out headerValue)) {
            ContentType = headerValue.ToString();
        }
    }

    public string ContentType { get; private set; }

    public string FileName {
        get { return filename ?? String.Empty; }
        set { filename = value; }
    }

    public string Content { get; set; }

    public override void ExecuteResult(ControllerContext context) {
        HttpResponseBase response = null;
        if (context != null
            && context.HttpContext != null
            && ((response = context.HttpContext.Response) != null)) {

            response.Buffer = true;
            response.Clear();

            response.ContentType = ContentType;

            if (!String.IsNullOrWhiteSpace(FileName)) {
                string headerValue = ContentDispositionUtil.GetHeaderValue(FileName);
                response.AppendHeader("Content-Disposition", headerValue);
            }

            response.Write(Content);
            response.End();
        }
    }

    internal static class ContentDispositionUtil {
        public static string GetHeaderValue(string filename) {
            System.Net.Http.Headers.ContentDispositionHeaderValue contentDisposition = null;
            string headerValue = String.Format("attachment; filename=\"{0}\"", filename);
            if (System.Net.Http.Headers.ContentDispositionHeaderValue.TryParse(headerValue, out contentDisposition)) {
                var result = contentDisposition.ToString();
                return result;
            } else {
                throw new ArgumentException("Content Disposition Header Value not well formatted - " + headerValue, "FileName");
            }
        }
    }
}