MVC 控制器 Returns CSV 但不使用 AJAX 下载
MVC Controller Returns CSV but does not Download Using AJAX
在我的控制器中,我正在使用 ServiceStack.Text 序列化一个列表并希望将其 return 发送给客户端。
我正在传递 json,它被传递并操作到一个对象列表中,然后我想 return 作为 csv。我可以确认这部分正在工作。客户端报告请求成功但没有文件可供下载。如果我 console.log 它打印 csv 字符串的响应。
我实际上收到了一个 json 字符串的列表,我反序列化并附加到单个 list.Again,我可以确认这是按预期工作的。
代码如下:
[ValidateInput(false)]
[HttpPost]
public FileContentResult DownloadCSV(List<string> json, string delimiter, string method)
{
var respCSV ="";
if (method == "combine")
{
List<AgmtToCSV> comb = new List<AgmtToCSV>();
foreach (var i in json)
{
var d = Newtonsoft.Json.JsonConvert.DeserializeObject<List<AgmtToCSV>>(i);
foreach (var u in d)
{
comb.Add(u);
}
}
var csv = CsvSerializer.SerializeToCsv(comb);
respCSV = csv;
}
return File(new System.Text.UTF8Encoding().GetBytes(respCSV), "text/csv", "ExpirationReport.csv");
//return File(respCSV);
}
编辑
响应如下所示:
Cache-Control:private
Content-Disposition:attachment; filename=ExpirationReport.csv
Content-Encoding:gzip
Content-Length:3117
Content-Type:text/csv
Date:Thu, 20 Jul 2017 17:42:16 GMT
Server:Microsoft-IIS/8.0
Vary:Accept-Encoding
X-AspNet-Version:4.0.30319
X-AspNetMvc-Version:5.2
X-Powered-By:ASP.NET
X-SourceFiles:=?UTF-8?B?SDpcZGV2ZWxvcG1lbnRcQWdyZWVtZW50LVZpZXdlclxBViAxLjEuMyBkZXZcQVZcQVZcSG9tZVxEb3dubG9hZENTVg==?=
这是 jquery 请求及其处理成功响应的方式。
$.post('@Url.Action("DownloadCSV", "Home")', { "json":dta, "delimiter":del, "method":"combine"}, function (r) {
console.log("Success");
console.log(r);
});
更新 - 解决方案
能够使它与已接受的答案一起工作:成功功能是这里的关键。它创建一个 link 指向下载然后启动它。
$.post('@Url.Action("DownloadCSV", "Home")', { "json":dta, "delimiter":del, "method":"combine"}, function (r) {
console.log("Success");
var link = document.createElement("a");
link.id = "lnkDwnldLnk";
var converted = r;
document.body.appendChild(link);
var csv = converted;
blob = new Blob([csv], { type: 'text/csv' });
window.URL = window.URL || window.webkitURL;
var csvUrl = window.URL.createObjectURL(blob);
var filename = 'ExpirationReport.csv';
$("#lnkDwnldLnk")
.attr({
'download': filename,
'href': csvUrl
});
var ua = window.navigator.userAgent;
var msie = ua.indexOf("MSIE ");
if (msie > 0 || !!navigator.userAgent.match(/Trident.*rv\:11\./)) // If Internet Explorer, return version number
{
window.navigator.msSaveOrOpenBlob(blob, filename);
}
else {
$('#lnkDwnldLnk')[0].click();
}
document.body.removeChild(link);
});
我不确定我的回答是否完全符合您的要求,但仍然如此。我有我正在使用的这段代码,它基本上接收一个 JSON 对象,将其转换为 CSV 格式并在浏览器中下载。
转到服务以获取对象列表的控制器代码,returns它作为 JSON。
public ActionResult DownLoadExcel(long BatchNumber)
{
Context context = new Context();
IQueryable<string> ICodeList = context.Codes.OrderByDescending(c => c.CreatedDateTime).Where(c => c.BatchNumber == BatchNumber).Select(c => c.Id); ;
var codeList = ICodeList.ToList();
return Json(codeList, JsonRequestBehavior.AllowGet);
}
从控制器获取 JSON 列表并将其转换为 CSV 的 AJAX 调用。然后它创建并伪造一个锚点并模拟点击它来触发下载。:
<script type="text/javascript">
function getExcel(batchNumber)
{
$.ajax({
type: 'GET',
url: '@Url.Action("DownloadExcel", "BatchCode")',
data: { BatchNumber: batchNumber },
cache: false,
success: function (result) {
var converted = ConvertToCSV(result);
//this trick will generate a temp "a" tag
var link = document.createElement("a");
link.id = "lnkDwnldLnk";
//this part will append the anchor tag and remove it after automatic click
document.body.appendChild(link);
var csv = converted;
blob = new Blob([csv], { type: 'text/csv' });
window.URL = window.URL || window.webkitURL;
var csvUrl = window.URL.createObjectURL(blob);
var filename = 'file.csv';
$("#lnkDwnldLnk")
.attr({
'download': filename,
'href': csvUrl
});
var ua = window.navigator.userAgent;
var msie = ua.indexOf("MSIE ");
if (msie > 0 || !!navigator.userAgent.match(/Trident.*rv\:11\./)) // If Internet Explorer, return version number
{
window.navigator.msSaveOrOpenBlob(blob, filename);
}
else{
$('#lnkDwnldLnk')[0].click();
}
document.body.removeChild(link);
}
});
}
function ConvertToCSV(objArray) {
var array = typeof objArray != 'object' ? JSON.parse(objArray) : objArray;
var str = '';
for (var i = 0; i < array.length; i++) {
var line = array[i];
str += line + '\r\n';
}
return str;
}
</script>
最后你需要在 HTML
中清空 a
<a hidden="hidden"></a>
在我的控制器中,我正在使用 ServiceStack.Text 序列化一个列表并希望将其 return 发送给客户端。
我正在传递 json,它被传递并操作到一个对象列表中,然后我想 return 作为 csv。我可以确认这部分正在工作。客户端报告请求成功但没有文件可供下载。如果我 console.log 它打印 csv 字符串的响应。
我实际上收到了一个 json 字符串的列表,我反序列化并附加到单个 list.Again,我可以确认这是按预期工作的。
代码如下:
[ValidateInput(false)]
[HttpPost]
public FileContentResult DownloadCSV(List<string> json, string delimiter, string method)
{
var respCSV ="";
if (method == "combine")
{
List<AgmtToCSV> comb = new List<AgmtToCSV>();
foreach (var i in json)
{
var d = Newtonsoft.Json.JsonConvert.DeserializeObject<List<AgmtToCSV>>(i);
foreach (var u in d)
{
comb.Add(u);
}
}
var csv = CsvSerializer.SerializeToCsv(comb);
respCSV = csv;
}
return File(new System.Text.UTF8Encoding().GetBytes(respCSV), "text/csv", "ExpirationReport.csv");
//return File(respCSV);
}
编辑
响应如下所示:
Cache-Control:private
Content-Disposition:attachment; filename=ExpirationReport.csv
Content-Encoding:gzip
Content-Length:3117
Content-Type:text/csv
Date:Thu, 20 Jul 2017 17:42:16 GMT
Server:Microsoft-IIS/8.0
Vary:Accept-Encoding
X-AspNet-Version:4.0.30319
X-AspNetMvc-Version:5.2
X-Powered-By:ASP.NET
X-SourceFiles:=?UTF-8?B?SDpcZGV2ZWxvcG1lbnRcQWdyZWVtZW50LVZpZXdlclxBViAxLjEuMyBkZXZcQVZcQVZcSG9tZVxEb3dubG9hZENTVg==?=
这是 jquery 请求及其处理成功响应的方式。
$.post('@Url.Action("DownloadCSV", "Home")', { "json":dta, "delimiter":del, "method":"combine"}, function (r) {
console.log("Success");
console.log(r);
});
更新 - 解决方案
能够使它与已接受的答案一起工作:成功功能是这里的关键。它创建一个 link 指向下载然后启动它。
$.post('@Url.Action("DownloadCSV", "Home")', { "json":dta, "delimiter":del, "method":"combine"}, function (r) {
console.log("Success");
var link = document.createElement("a");
link.id = "lnkDwnldLnk";
var converted = r;
document.body.appendChild(link);
var csv = converted;
blob = new Blob([csv], { type: 'text/csv' });
window.URL = window.URL || window.webkitURL;
var csvUrl = window.URL.createObjectURL(blob);
var filename = 'ExpirationReport.csv';
$("#lnkDwnldLnk")
.attr({
'download': filename,
'href': csvUrl
});
var ua = window.navigator.userAgent;
var msie = ua.indexOf("MSIE ");
if (msie > 0 || !!navigator.userAgent.match(/Trident.*rv\:11\./)) // If Internet Explorer, return version number
{
window.navigator.msSaveOrOpenBlob(blob, filename);
}
else {
$('#lnkDwnldLnk')[0].click();
}
document.body.removeChild(link);
});
我不确定我的回答是否完全符合您的要求,但仍然如此。我有我正在使用的这段代码,它基本上接收一个 JSON 对象,将其转换为 CSV 格式并在浏览器中下载。
转到服务以获取对象列表的控制器代码,returns它作为 JSON。
public ActionResult DownLoadExcel(long BatchNumber)
{
Context context = new Context();
IQueryable<string> ICodeList = context.Codes.OrderByDescending(c => c.CreatedDateTime).Where(c => c.BatchNumber == BatchNumber).Select(c => c.Id); ;
var codeList = ICodeList.ToList();
return Json(codeList, JsonRequestBehavior.AllowGet);
}
从控制器获取 JSON 列表并将其转换为 CSV 的 AJAX 调用。然后它创建并伪造一个锚点并模拟点击它来触发下载。:
<script type="text/javascript">
function getExcel(batchNumber)
{
$.ajax({
type: 'GET',
url: '@Url.Action("DownloadExcel", "BatchCode")',
data: { BatchNumber: batchNumber },
cache: false,
success: function (result) {
var converted = ConvertToCSV(result);
//this trick will generate a temp "a" tag
var link = document.createElement("a");
link.id = "lnkDwnldLnk";
//this part will append the anchor tag and remove it after automatic click
document.body.appendChild(link);
var csv = converted;
blob = new Blob([csv], { type: 'text/csv' });
window.URL = window.URL || window.webkitURL;
var csvUrl = window.URL.createObjectURL(blob);
var filename = 'file.csv';
$("#lnkDwnldLnk")
.attr({
'download': filename,
'href': csvUrl
});
var ua = window.navigator.userAgent;
var msie = ua.indexOf("MSIE ");
if (msie > 0 || !!navigator.userAgent.match(/Trident.*rv\:11\./)) // If Internet Explorer, return version number
{
window.navigator.msSaveOrOpenBlob(blob, filename);
}
else{
$('#lnkDwnldLnk')[0].click();
}
document.body.removeChild(link);
}
});
}
function ConvertToCSV(objArray) {
var array = typeof objArray != 'object' ? JSON.parse(objArray) : objArray;
var str = '';
for (var i = 0; i < array.length; i++) {
var line = array[i];
str += line + '\r\n';
}
return str;
}
</script>
最后你需要在 HTML
中清空 a<a hidden="hidden"></a>