19

我需要在具有 .csv 文件类型的 ASP.NET MVC 应用程序中创建一个 ActionResult。

我将向我的营销合作伙伴提供一个“请勿致电”电子邮件列表,并且我希望它在文件类型中具有 .csv 扩展名。然后它会自动在 Excel 中打开。

 http://www.example.com/mailinglist/donotemaillist.csv?password=12334

我已经成功地做到了这一点,但我想确保这是绝对最好和推荐的方法。

    [ActionName("DoNotEmailList.csv")]
    public ContentResult DoNotEmailList(string username, string password)
    {
            return new ContentResult()
            {
                Content = Emails.Aggregate((a,b)=>a+Environment.NewLine + b), 
                ContentType = "text/csv"
            };
    }

这个 Actionmethod 会很好地响应上面的链接。

我只是想知道这样的文件扩展名与任何不同版本的 IIS、任何类型的 ISAPI 过滤器或我现在想不到的任何东西是否有任何意外冲突的可能性。

我需要 100% 确定,因为我将把它提供给外部合作伙伴,并且不想以后改变主意。我真的看不到任何问题,但也许有一些模糊的东西 - 或者另一种更像“MVC”的方式来做到这一点。

4

4 回答 4

29

我使用 FileContentResult 操作也做了类似的事情。

public FileContentResult DoNotEmailList(string username, string password)
{
        string csv = Emails.Aggregate((a,b)=>a+Environment.NewLine + b);
        byte[] csvBytes = ASCIIEncoding.ASCII.GetBytes( csv );
        return File(csvBytes, "text/csv", "DoNotEmailList.csv");
}

它将为您添加 content-disposition 标头。

于 2011-10-19T12:55:20.027 回答
22

在这种情况下,我认为您的响应必须包含“Content-Disposition”标头。像这样创建自定义 ActionResult:

public class MyCsvResult : ActionResult {

    public string Content {
        get;
        set;
    }

    public Encoding ContentEncoding {
        get;
        set;
    }

    public string Name {
        get;
        set;
    }

    public override void ExecuteResult(ControllerContext context) {
        if (context == null) {
            throw new ArgumentNullException("context");
        }

        HttpResponseBase response = context.HttpContext.Response;

        response.ContentType = "text/csv";

        if (ContentEncoding != null) {
            response.ContentEncoding = ContentEncoding;
        }

        var fileName = "file.csv";

        if(!String.IsNullOrEmpty(Name)) {
            fileName = Name.Contains('.') ? Name : Name + ".csv";
        }

        response.AddHeader("Content-Disposition",
            String.Format("attachment; filename={0}", fileName));

        if (Content != null) {
            response.Write(Content);
        }
    }
}

并在您的 Action 而不是 ContentResult 中使用它:

return new MyCsvResult {
    Content = Emails.Aggregate((a,b) => a + Environment.NewLine + b)
    /* Optional
     * , ContentEncoding = ""
     * , Name = "DoNotEmailList.csv"
     */
};
于 2009-06-13T12:19:46.110 回答
6

这就是我做类似事情的方式。我将其视为下载:

var disposition = String.Format(
  "attachment;filename=\"{0}.csv\"", this.Model.Name);
Response.AddHeader("content-disposition", disposition);

这应该在浏览器中显示为具有给定文件名的文件下载。

不过,我想不出你的不起作用的原因。

于 2009-06-13T04:03:04.853 回答
0

您接受的答案已经足够好,但它在输出时将输出的内容保留在内存中。如果它生成的文件相当大怎么办?例如,当您转储 SQL 表的内容时。您的应用程序可能内存不足。在这种情况下,您需要的是使用 FileStreamResult。将数据馈送到流中的一种方法是使用管道,正如我在此处描述的那样

于 2015-06-05T16:03:20.940 回答