MVC javascript方法调用没有启动excel保存对话框

时间:2011-12-05 08:37:00

标签: javascript jquery asp.net-mvc

我有一段javascript,它通过数组和一个int发送。

var InvoicesAndId = { values: indexArray, Id:3 };

$.ajax({
type: "POST",
url: 'Invoice/Export',
data: postData,
success: function (data) {location.replace(window.location.pathname); },
dataType: "json",
tradional: true
});

所以这会调用我的Controller上的方法:

public void Export(InvoicesAndId invoicesAndId)
{
...

Response.AppendHeader("content-disposition", "attachment; filename" + "invoices.csv");
Response.ContentType = "application/ms-excel";
Response.ContentEncoding = System.Text.Encoding.GetEncoding("utf-8");
Response.Write("word");
Response.End();
}

因此,使用调试器,我发现InvoicesAndId已正确填充。问题是应该出现一个对话框,说明是打开还是保存excel文件。

这不会发生。

我知道这与我如何调用该函数有关,因为如果我用ActionLink调用它,则会出现对话框。

我做错了什么?是否与ajax调用有关?

如何解决这个问题?我不能使用ActionLink,因为可能没有办法填充参数。

3 个答案:

答案 0 :(得分:3)

  

我做错了什么?

在ASP.NET MVC中,您通常会调用返回ActionResult的控制器操作,它们不使用Response.Write

public ActionResult Export(InvoicesAndId invoicesAndId)
{
    Response.ContentType = "application/ms-excel";
    byte[] excel = Encoding.UTF8.GetBytes("word"); // Obviously not a valid Excel
    return File(excel, "application/ms-excel", "invoices.csv");
}

现在显然将内容类型设置为"application/ms-excel"并将一个simlpe字符串(例如word)写入响应,除了损坏的Excel文件外,不要指望得到任何内容。但我想这只是一个例子,你将修复并编写一个真正的Excel文件。

如果这是您要发送的内容,请将您的内容类型调整为CSV:

Response.ContentType = "text/csv";

现在这只是第一部分。第二部分和实际处于问题根源的部分是您正在使用AJAX来调用此控制器操作。您不能使用AJAX来调用应该下载文件的控制器操作。仅仅因为当您使用AJAX调用此类操作时,您最终会在成功回调中传递data javascript变量并包含CSV文件。显然,既然你现在在客户端,你就无法做任何事情。出于安全原因,您无法将其保存到客户端,也不能提示下载(已经下载)。

因此,您应该使用标准链接或表单提交来调用应该流式传输文件的控制器操作。

答案 1 :(得分:2)

您不必使用$ .ajax,您可以使用$.param()序列化参数并将位置设置为构建的网址;

var InvoicesAndId = { values: indexArray, Id:3 };
location.href = 'Invoice/Export?' + $.param(InvoicesAndId, true);

这样,浏览器会尝试导航到新的网址,但由于它会返回一个文件,因此会出现文件打开/保存对话框,用户不会导航到另一个网址。

答案 2 :(得分:0)

public class ExcelResult : ActionResult
{
  public string FileName { get; set; }
  public string Path { 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/vnd.ms-excel";
          context.HttpContext.Response.WriteFile(context.HttpContext.Server.MapPath(Path));   
  }
}

public ExcelResult GetExcelFile()
{  
    return new ExcelResult
              {
                    FileName = "sample.xls", Path = "~/Content/sample.xls"
              };
              }`