.NET Core Razor Pages+ClosedXML+Unobtrusive AJAX 文件下载失败
问题原因
你用了AJAX提交表单,但浏览器不会自动处理AJAX请求返回的文件流响应,所以代码执行无报错但没有下载动作。AJAX默认用于获取JSON/文本数据,无法直接触发文件下载。
解决方案
方案1:改用普通表单提交(最简单)
直接移除form标签里的data-ajax相关属性,让表单以普通方式提交,浏览器会自动处理后端返回的文件流:
<form class="d-flex flex-row" method="post" asp-page-handler="ExportToExcel"> <button type="submit" class="btn btn-primary" data-bs-toggle="tooltip" data-bs-placement="top" title="Export to Excel"><i class="fa-light fa-cloud-arrow-down"></i></button> </form>
后端代码无需修改,保持原样即可。
方案2:保留AJAX,前端手动触发下载(适合需要页面不刷新的场景)
如果必须用AJAX,需要后端返回文件的Base64编码,再由前端处理并触发下载:
后端修改(返回Base64数据)
public IActionResult OnPostExportToExcel() { AssetsList = _context.Assets.ToList(); using (var workbook = new XLWorkbook()) { var worksheet = workbook.Worksheets.Add("Assets"); var currentRow = 1; worksheet.Cell(currentRow, 1).Value = "AssetName"; // 填充其他列逻辑... foreach (Asset asset in AssetsList) { currentRow++; worksheet.Cell(currentRow, 1).Value = asset.AssetName ?? ""; // 填充其他列逻辑... } var fileName = "AssetsExport-" + DateTime.Now.ToString("yyyyMMdd-HHmmssfff") + ".xlsx"; using (var stream = new MemoryStream()) { workbook.SaveAs(stream); stream.Position = 0; byte[] fileBytes = stream.ToArray(); string base64 = Convert.ToBase64String(fileBytes); return Json(new { fileName = fileName, fileBase64 = base64, contentType = "application/vnd.openxmlformats-officedocument.spreadsheetml.sheet" }); } } }
前端修改(处理Base64并触发下载)
<form class="d-flex flex-row" method="post" asp-page-handler="ExportToExcel" data-ajax="true" data-ajax-method="post" data-ajax-success="handleDownload" data-ajax-failure="ajaxValidationHandler"> <button type="submit" class="btn btn-primary" data-bs-toggle="tooltip" data-bs-placement="top" title="Export to Excel"><i class="fa-light fa-cloud-arrow-down"></i></button> </form> <script> function handleDownload(response) { const byteCharacters = atob(response.fileBase64); const byteNumbers = new Array(byteCharacters.length); for (let i = 0; i < byteCharacters.length; i++) { byteNumbers[i] = byteCharacters.charCodeAt(i); } const byteArray = new Uint8Array(byteNumbers); const blob = new Blob([byteArray], { type: response.contentType }); const url = URL.createObjectURL(blob); const a = document.createElement('a'); a.href = url; a.download = response.fileName; document.body.appendChild(a); a.click(); URL.revokeObjectURL(url); document.body.removeChild(a); } </script>
内容的提问来源于stack exchange,提问作者s15199d
相关产品推荐
相关产品推荐

