javascript - 从操作中返回文件并使用 AJAX 下载
问题描述
这可能是重复的,但我还没有找到解决方案。
在我正在开发的应用程序中,有两个export
按钮可以将 Excel 文件下载到用户的计算机上。
一个导出按钮执行 POST 表单方法,将参数路由到操作:
<input type="submit" value="EXPORT" id="exportButton" asp-action="ExportResultsData"
asp-route-ClientID="@listItem.ClientID" asp-route-ProcessingType="@listItem.ProcessingType"
asp-route-ProgressType="@Model.ProgressType" asp-route-FileName="@listItem.FileName" />
单击时,这些值将路由到控制器操作,它们用于创建文件并将其返回到下载文件的浏览器。都好。
正如我所说,我有另一个按钮需要下载另一个 Excel 文件。但是,这个不同,因为视图模型不包含路由到其控制器操作所需的所有值。每次单击按钮时,我都需要调用一个 JavaScript 函数并获取一个具有以下结构的 JSON 对象:
{
"draw": 1,
"columns": [
{
"data": "Column1",
"name": "Column1",
"searchable": true,
"orderable": true,
"search": {
"value": "",
"regex": false
}
},
{
"data": "Column2",
"name": "Column2",
"searchable": true,
"orderable": true,
"search": {
"value": "",
"regex": false
}
},
{
"data": "Column3",
"name": "Column3",
"searchable": true,
"orderable": true,
"search": {
"value": "",
"regex": false
}
},
{
"data": "Column4",
"name": "Column4",
"searchable": true,
"orderable": true,
"search": {
"value": "",
"regex": false
}
}
],
"order": [
{
"column": 0,
"dir": "asc"
}
],
"start": 0,
"length": 15,
"search": {
"value": "",
"regex": false
},
"ClientID": 8,
"FeedbackID": "8",
"ProcessingType": "Import"
}
每次获取这些参数时,某些值可能会发生变化,并且列数可能会增加/减少。
我可以到达控制器操作,将参数绑定到模型,并成功生成 Excel 文件,但文件没有下载,只是返回到 AJAXsuccess
部分:
function ExportFeedbackData(clientID, feedbackID, processingType) {
var jqueryParams = GetJqueryParams();
$.ajax({
url: '/Client/ExportFeedbackData',
type: 'POST',
data: {
DatatablesParameters: jqueryParams,
ClientID: clientID,
FeedbackID: feedbackID,
ProcessingType: processingType,
},
success: function (exportedFile) {
console.log(exportedFile);
//file data just returns here and doesn't download
},
error: function (errormsg) {
console.log(errormsg);
}
});
}
控制器动作:
//"DatatablesParameters" refers to parameters sent from a JS plugin called Datatables https://datatables.net/
//https://datatables.net/manual/server-side
public IActionResult ExporFeedbackData(DataTablesParameters DatatablesParameters, int ClientID, int FeedbackID, string ProcessingType)
{
DataTable dt = _processingService.ReturnDataTable(DatatablesParameters, ClientID, FeedbackID, ProcessingType);
using (ExcelPackage package = new ExcelPackage())
{
ExcelWorksheet worksheet = package.Workbook.Worksheets.Add(ProcessingType);
worksheet.Cells["A1"].LoadFromDataTable(dt, PrintHeaders: true);
for (var i = 0; i < dt.Columns.Count; i++)
{
worksheet.Cells.AutoFitColumns();
}
return File(package.GetAsByteArray(), XlsxContentType, $"{ProcessingType}.xlsx"); //Excel file returned
}
}
所以,我想要的是能够用 AJAX 下载文件,但我不知道该怎么做。该文件也可能很大。我也很想以某种方式消除 AJAX 并动态生成<input>
标签,但每次我导出 jquery 对象中的值可能会有所不同。我也对其他解决方案持开放态度。
我主要担心清洁度和可靠性。通过表单提交,您只需单击按钮即可下载。但是对于 AJAX,它看起来更加混乱。
解决方案
AJAX 请求是一个瘦客户端请求。响应不会自动发生任何事情;程序员需要对响应执行任何操作。由于要提示文件下载,因此需要在 href 中动态创建一个将文件数据作为对象 URL 的锚链接,然后“单击”它。
let a = document.createElement('a');
let url = window.URL.createObjectURL(exportedFile);
a.href = url;
a.download = 'myfile.xlsx';
document.body.append(a);
a.click();
a.remove();
window.URL.revokeObjectURL(url);
推荐阅读
- sql - 日期失败时的索引时间戳
- google-cloud-platform - 到 Cloud Function Webhook 的 GCP 通知(Stackdriver)不起作用
- html - 使用 React 钩子从 HTML 元素中删除/添加类名
- javascript - 如何通过解析字符串生成树结构?
- python - 用标签(x)预测机器学习目标(y),然后用目标计算标签
- python - 合并/合并/连接两个数据帧,根据索引从第二个数据帧中删除重复行
- firebase - 错误:flutter/lib/ui/ui_dart_state.cc(209)] 未处理的异常:[core/duplicate-app] 一个名为“[DEFAULT]”的 Firebase 应用程序已经存在
- python - 根据列值列表删除多行
- excel - 计算公式时如何使用excel VBA将公式复制到相邻单元格(使用相对引用)?
- java - 连接丢失后,Hibernate 自动与 sql-server 重新连接