MVC javascript方法调用未打开excel保存对话框
我有一段javascript,它通过数组和int发送数据MVC javascript方法调用未打开excel保存对话框,javascript,jquery,asp.net-mvc,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 }
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
});
因此,这将调用控制器上的方法:
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,因为可能没有填充参数的方法
我做错了什么
在ASP.NET MVC中,您通常调用返回ActionResult的控制器操作,它们不使用响应。请编写:
现在很明显,将内容类型设置为application/msexcel并将word之类的simlpe字符串写入响应,除了损坏的excel文件之外,别指望得到任何东西。但我想这只是一个例子,您将修复并编写一个真正的Excel文件
或将您的内容类型调整为CSV(如果您打算发送):
Response.ContentType = "text/csv";
这只是第一部分。第二部分,也是问题的根源,是您正在使用AJAX来调用这个控制器操作。您不能使用AJAX调用应该下载文件的控制器操作。原因很简单,当您使用AJAX调用这样一个操作时,您最终会在成功回调中使用传递给它的数据javascript变量并包含CSV文件。显然,因为你现在是在客户端,你不能用它做任何事情。出于安全原因,您不能将其保存到客户端,也不能提示下载它已下载
因此,您应该使用标准链接或表单提交来调用控制器操作,这些操作应该是流式传输要下载的文件
我做错了什么
在ASP.NET MVC中,您通常调用返回ActionResult的控制器操作,它们不使用响应。请编写:
现在很明显,将内容类型设置为application/msexcel并将word之类的simlpe字符串写入响应,除了损坏的excel文件之外,别指望得到任何东西。但我想这只是一个例子,您将修复并编写一个真正的Excel文件
或将您的内容类型调整为CSV(如果您打算发送):
Response.ContentType = "text/csv";
这只是第一部分。第二部分,也是问题的根源,是您正在使用AJAX来调用这个控制器操作。您不能使用AJAX调用应该下载文件的控制器操作。原因很简单,当您使用AJAX调用这样一个操作时,您最终会在成功回调中使用传递给它的数据javascript变量并包含CSV文件。显然,因为你现在是在客户端,你不能用它做任何事情。出于安全原因,您不能将其保存到客户端,也不能提示下载它已下载
因此,您应该使用标准链接或表单提交来调用控制器操作,这些操作应该是要下载的流文件。您不必使用$.ajax,您可以使用序列化参数并将位置设置为构造的url
var InvoicesAndId = { values: indexArray, Id:3 };
location.href = 'Invoice/Export?' + $.param(InvoicesAndId, true);
这样,浏览器将尝试导航到新的url,但由于它返回一个文件,将出现文件打开/保存对话框,用户将不会导航到另一个url。您不必使用$.ajax,您可以使用序列化参数并将位置设置为构造的url
var InvoicesAndId = { values: indexArray, Id:3 };
location.href = 'Invoice/Export?' + $.param(InvoicesAndId, true);
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));
}
}
这样,浏览器将尝试导航到新的url,但由于它返回一个文件,将出现文件打开/保存对话框,用户将不会导航到另一个url
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));
}
}
及
及
我不明白。你为什么要改变被接受的答案?你的问题不是关于MVC ActionResult,而是关于javascript。达林的回答很好,我也投了赞成票。我的回答是错误的还是无用的?我错过什么了吗?我不明白。你为什么要改变被接受的答案?你的问题不是关于MVC ActionResult,而是关于javascript。达林的回答很好,我也投了赞成票。我的回答是错误的还是无用的?我错过什么了吗?