Blazor Server调用JavaScript函数saveFile提示未定义问题求助
解决Blazor调用JS函数
saveFile提示未定义的问题 问题描述
在Blazor Razor页面后台调用saveFile JavaScript函数时,持续抛出函数未定义的错误,具体报错信息如下:
[2023-11-14T15:49:45.869Z] Error: Microsoft.JSInterop.JSException: Could not find 'saveFile' ('saveFile' was undefined). findFunction/<@https://localhost:7261/_framework/blazor.server.js:1:497 findFunction@https://localhost:7261/_framework/blazor.server.js:1:465 E@https://localhost:7261/_framework/blazor.server.js:1:2606 beginInvokeJSFromDotNet/s<@https://localhost:7261/_framework/blazor.server.js:1:3494 beginInvokeJSFromDotNet@https://localhost:7261/_framework/blazor.server.js:1:3475 _invokeClientMethod/<@https://localhost:7261/_framework/blazor.server.js:1:72077 _invokeClientMethod@https://localhost:7261/_framework/blazor.server.js:1:72063 _processIncomingData@https://localhost:7261/_framework/blazor.server.js:1:70105 kt/this.connection.onreceive@https://localhost:7261/_framework/blazor.server.js:1:64508 connect/</o.onmessage@https://localhost:7261/_framework/blazor.server.js:1:48842 at Microsoft.JSInterop.JSRuntime.InvokeAsync[TValue](Int64 targetInstanceId, String identifier, Object[] args) at HR_Taxonomy_Change_Management.Pages.Administration.GetSpreadsheet() in C:\Users\v-reedchris\source\repos\HR Taxonomy Change Management\HR Taxonomy Change Management\Pages\Administration.razor.cs:line 169 at Microsoft.AspNetCore.Components.ComponentBase.CallStateHasChangedOnAsyncCompletion(Task task) at Microsoft.AspNetCore.Components.RenderTree.Renderer.GetErrorHandledTask(Task taskToHandle, ComponentState owningComponentState) blazor.server.js:1:116297
已尝试的操作:
- 将JS文件放置在
wwwroot/js/saveFile.js及项目根目录 - 调整
_Layout页面中的JS加载顺序 - 浏览器调试器可定位到对应的JS文件,但问题仍未解决
相关代码
C# 触发下载代码(Razor后台)
private async Task GetSpreadsheet() { IBinaryWorkbookFormatProvider formatProvider = new Telerik.Windows.Documents.Spreadsheet.FormatProviders.OpenXml.Xlsx.XlsxFormatProvider(); var docService = await AdminDomain.GetReportAsync().ConfigureAwait(false); byte[] bytesFromWorkbook = formatProvider.Export(docService); await JSRuntime.InvokeAsync<object>("saveFile", "test.xlsx", "application/vnd.openxmlformats-officedocument.spreadsheetml.sheet", bytesFromWorkbook); }
JavaScript 原函数代码
function saveFile(file, contentType, content) { // Create the URL const file = new File([content], filename, { type: contentType }); const exportUrl = URL.createObjectURL(file); // Create the <a> element and click on it const a = document.createElement("a"); document.body.appendChild(a); a.href = exportUrl; a.download = filename; a.target = "_self"; a.click(); // We don't need to keep the object URL, let's release the memory // On older versions of Safari, it seems you need to comment this line... URL.revokeObjectURL(exportUrl); }
解决方案
1. 将JS函数挂载到全局window对象
Blazor的JSInterop只能访问全局作用域的函数,必须把saveFile绑定到window上,同时修正原函数的参数名错误:
window.saveFile = function(filename, contentType, content) { // 修正:原函数参数名错误,第一个参数应为filename,且函数内使用的filename变量未定义 const file = new File([content], filename, { type: contentType }); const exportUrl = URL.createObjectURL(file); const a = document.createElement("a"); document.body.appendChild(a); a.href = exportUrl; a.download = filename; a.target = "_self"; a.click(); URL.revokeObjectURL(exportUrl); document.body.removeChild(a); // 清理创建的DOM元素,避免内存泄漏 }
2. 确保JS文件正确加载
在_Layout.cshtml(Blazor Server场景)中,按以下方式加载JS文件:
<!-- 放在<body>末尾,在blazor.server.js之前加载,或添加defer属性保证DOM加载完成后执行 --> <script src="~/js/saveFile.js" defer></script> <script src="_framework/blazor.server.js"></script>
如果是单个Razor组件单独引用JS,可在组件内添加:
@inject IJSRuntime JSRuntime @implements IAsyncDisposable <script src="~/js/saveFile.js"></script>
3. 验证函数是否全局注册
打开浏览器控制台,执行window.saveFile:
- 如果返回函数体,说明已成功全局注册
- 如果返回
undefined,检查:- JS文件路径是否正确,查看浏览器Network标签确认文件是否成功加载(状态码200)
- JS文件是否存在语法错误,查看Console标签的报错信息
4. 处理Byte数组的传递
Blazor传递byte[]到JS时会自动转换为Uint8Array,如果出现文件损坏问题,可显式转换为ArrayBuffer:
window.saveFile = function(filename, contentType, content) { const arrayBuffer = content instanceof Uint8Array ? content.buffer : content; const file = new File([arrayBuffer], filename, { type: contentType }); // 后续逻辑不变 }
内容的提问来源于stack exchange,提问作者USMC6072
相关产品推荐
相关产品推荐

